WordPress Themes
A WordPress theme is the set of files containing PHP and HTML which sit on-top of the core WordPress application and convert its raw response data in to usable web pages. Themes determine the look and functionality of a WordPress website.
- A theme defines the presentation or theming layer of the WordPress application.
- A theme enables what WP features are available. Common WP features like Sidebars (Widgets) and Menus are not enabled by default and must be defined and configured in the theme.
- WordPress will not function without an active theme. Many themes can be installed but only one can be active at a time. Themes are activated from within the WordPress admin panel. All versions of WordPress ship with a default theme.
- WP can use a child theme to allow changes to an existing theme without having to create the theme and all it's functionality from scratch. A child theme defines only the differences between it and its parent theme. WordPress first looks at the child for files but falls-back to the parent if nothing is found.
Theme Files
- Every WordPress theme (child or parent) must have a uniquely named directory under
wp-content/themes/. - Each theme directory requires at least the two files
style.cssandindex.php, however the filefunctions.phpis also common. - Although not required, a child theme directory should be named after the parent theme's directory by adding
-child. For example, if you are creating a child theme for the twentytwentythree theme, the child directory would be named twentytwentythree-child. - There are no limits to what additional files and directories can be placed in a theme directory.
A WordPress theme can be setup and accomplish everything it needs to with these three files:
syles.css
- The
MARKDOWN_HASHda232d78aa810382f2dcdceae308ff8eMARKDOWNHASHfile is required and contains the WordPress Theme File Header_ formatted as a standard CSS doc-block comment. - Only the
Theme NameandTemplateare required for WP to detect and use a theme, however a standard theme usually comes with aDescription,Author, andVersionas well. If you plan to publish your theme you will need to add more info.
/*
Theme Name: My New Theme
Author: Me
Description: Some new theme.
Version: 1.0
*/
index.php
Templates (theme front-end)
The index.php file is required and is the primary template file for WordPress. Template files hold the page layout logic and include other template files to build the front-end (HTML page) for a request. Templates also define the Sidebar sections; areas of the page where Widgets and Menus can be placed by an admin user.
functions.php
Functions (theme back-end)
The functions.php file is optional, but is where most of the heavy lifting to change core WP functionality occurs. All WP features used in a theme are defined and enabled here, including API Hooks.
Theme Features
- Theme Features are functionality that may be optionally added to a theme.
- Themes must register each individual Theme Feature. Registration functions should be called in the theme's
functions.phpfile. - Adding Theme Features usually means getting an editable field in the admin page for the post, and some template methods to print output to your theme.
| Feature | Description |
|---|---|
| CSS and JS Files | JS and CSS files should be loaded into a template file using the wp_enqueue_script() and wp_enqueue_style() functions called from within the themes functions.php file. |
| Theme Markup | Allows themes to explicitly choose to apply HTML5 markup for search forms, comment forms, comment lists, gallery and caption. The second parameter accepts one or more values indicating which HTML5 features to support and is a required parameter for forward compatibility reasons. |
| Custom Headers | A custom header is an image that is chosen as the representative image in the theme top header section. |
| Editor Style | Allows links to a custom stylesheet file in the TinyMCE editor within the post edit screen. |
| Automatic Feed Links | Adds RSS feed links to HTML <head> tag. |
| Content Width | $content_width = 600;: Set the maximum allowed width for any content in the theme, like oEmbeds and images added to posts. |
| Custom Backgrounds | Provides for customization of the background color and image. |
| Post Formats | An admin can change how each post looks by choosing a Post Format from a radio-button list in the Publish meta box when saving a post. Options are aside, gallery, link, image, quote, status, video, audio, chat |
| Theme Logo | Allows themes to add custom logos. |
| Selective Refresh Support for Widgets | Users of the Customizer can selectively refresh a preview mechanism without refreshing the entire preview window. |
| Meta Boxes | Meta boxes are for admins to have custom functionality during post editing. How to Create Custom Meta Boxes |
The Loop
The Loop in WordPress.
// Does "The Loop" have posts?
if (have_posts()) {
// Get "The Loop".
while(have_posts()) {
// Get the post data.
$postData = the_post();
// Display post data with tags.
}
// If no posts are found...
} else {
echo '<p>Sorry, nothing here.</p>';
}
Enqueue CSS and JS Files
JS and CSS files should be loaded into a template file using the wp_enqueue_script() and wp_enqueue_style() functions called from within the themes functions.php file.
- Do not write link tags in the
header.phptemplate file. Enqueued files are pulled-in with thewp_head()template function. - Enqueuing ensures proper loading and caching, and allows the use of conditional tags to target specific pages.
- Including CSS and Javascript (developer.wordpress.org)
- wp_enqueue_style() (developer.wordpress.org)
- wp_enqueue_script() (developer.wordpress.org)
- https://developer.wordpress.org/themes/basics/including-css-javascript/
wp_enqueue_style()
Enqueue styles with wp_enqueue_style():
wp_enqueue_style( $handle, $src, $deps, $ver, $media );
| Parameter | Description |
|---|---|
$handle |
(string) (Required) Name of the stylesheet. Should be unique. |
$src |
(string) (Optional) Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory. Default value: `` |
$deps |
(string[]) (Optional) An array of registered stylesheet handles this stylesheet depends on. Default value: array() |
$ver |
(string/bool/null) (Optional) String specifying stylesheet version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added. Default value: false. |
$media |
(string) (Optional) The media for which this stylesheet has been defined. Accepts media types like 'all', 'print' and 'screen', or media queries like '(orientation: portrait)' and '(max-width: 640px)'. Default value: all |
function add_theme_scripts() {
wp_enqueue_style('my-styles', get_template_directory_uri() . '/css/my-styles.css', array('css-reset'), '1.1', 'all');
}
add_action( 'wp_enqueue_scripts', 'add_theme_scripts' );
wp_enqueue_script()
Enqueue scripts with wp_enqueue_script().
wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer);
| Parameter | Description |
|---|---|
$handle |
(string) (Required) Name of the script. Should be unique. |
$src |
(string) (Optional) Full URL of the script, or path of the script relative to the WordPress root directory. Default value: `` |
$deps |
(string[]) (Optional) An array of registered script handles this script depends on. Default value: array() |
$ver |
(string/bool/null) (Optional) String specifying script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added. Default value: false |
$in_footer |
(bool) (Optional) Whether to enqueue the script before </body> instead of in the <head>. Default false. |
function add_theme_scripts() {
wp_enqueue_script( 'my-script', get_template_directory_uri() . '/js/my-script.js', array('jquery'), 1.1, true);
}
add_action( 'wp_enqueue_scripts', 'add_theme_scripts' );
Read More Links
When post excerpts are displayed in WordPress they show a "read more" link, in the form of "[...]" if the text of the excerpt is longer than the maximum allowed excerpt character limit.
If you have not entered specific excerpt text into the "Excerpt" field while editing a post, then the content of your post is used, starting at the beginning and running up to the excerpts' maximum character limit.
There are at least two ways to customize the excerpt "read more" link. Both methods involve adding a custom PHP function to the function.php file in your theme.
Custom Link, Same Functionality
To replace the "read more" link ("[...]") with something else, but keep the functionality (i.e. "read more" links continue to appear only on long excerpts), write a function in the functions.php file of your theme which replaces the markup of the link. Attach your custom function to the "excerpt_more" filter hook like in the following example:
# File: /wp-content/themes/mytheme/functions.php
/**
* Customized post excerpt read-more links
* Replaces the default '[...]' link with a custom link.
*
* @param string $more The excerpt read-more link markup.
* @return string Returns the markup for the excerpt.
*/
function my_excerpt_more( $more ) {
# Return markup for the custom 'read more' link.
return '<a class="read-more" href="'. get_permalink( get_the_ID() ) . '">' . __('Read Full Post', 'my-theme') . '</a>';
}
# Add the custom function to the "excerpt_more" filter hook.
add_filter( 'excerpt_more', 'my_excerpt_more' );
Customize the Link
If you would like to redefine your own "read more" link and play with the functionality, you can create your own link. Attach your custom function to the “the_excerpt” filter hook:
# File: /wp-content/themes/mytheme/functions.php
/**
* Customized the post excerpt
* Adds a custom read-more link to all excerpts.
*
* @param string $exerptOutput The excerpt markup.
* @return string Returns the markup for the excerpt.
*/
function my_the_excerpt( $exerptOutput ){
# Append a custom 'read more' link to the excerpt output.
return $exerptOutput . '<a class="read-more" href="'. get_permalink( get_the_ID() ) . '">' . __('Read Full Post', 'my-theme') . '</a>';
}
# Add the custom function to the "the_excerpt" filter hook.
add_filter('the_excerpt', 'my_the_excerpt');
Next-Previous Links
<ul class="prev-next-nav">
<li class="prev">
<?php if( get_adjacent_post(false, '', true) ){ ?>
<span>Previous Post</span>
<?php previous_post_link( '%link', '%title' ); ?>
<?php } else { ?> <?php } ?>
</li>
<li class="next">
<?php if( get_adjacent_post(false, '', false) ){ ?>
<span>Next Post</span>
<?php next_post_link( '%link', '%title' ); ?>
<?php } else { ?> <?php } ?>
</li>
</ul>
Site Name
<?php echo get_bloginfo('name'); ?>
Page Title Tag
<h1><?php
# Default value.
$ww_pageTitle = '';
if( is_404() ){
$ww_pageTitle = '404 Page Not Found';
} elseif( is_search() ){
if( get_search_query() == '' ){
$ww_pageTitle = 'Search Results for Everything';
} else {
$ww_pageTitle = 'Search Results for: "' . get_search_query() . '"';
}
} elseif( is_home() ){
$ww_pageTitle = get_bloginfo( 'name' );
} elseif( is_single() || is_page() ){
$ww_pageTitle = get_the_title();
} elseif( is_category() ){
$ww_pageTitle = single_cat_title("", false);
} elseif( is_tag() ){
$ww_pageTitle = single_tag_title("", false);
} elseif( is_day() ) {
$ww_pageTitle = '<span>Daily Archive</span> ' . get_the_date();
} elseif( is_month() ){
$ww_pageTitle = '<span>Monthly Archive</span> ' . get_the_date('F Y');
} elseif( is_year() ){
$ww_pageTitle = '<span>Yearly Archive</span> ' . get_the_date('Y');
}
echo $ww_pageTitle;
?></h1>
Post Time
Get the time the post was published with get_the_time().
<?php echo get_the_time('F jS, Y'); ?>
Post Time Advanced
// Get the numberr of seconds past since the post was published.
$total_seconds_since_pub = current_time('timestamp') - get_the_time('U');
// Test if the post is older than 2 weeks.
if ($total_seconds_since_pub < 1209600) {
// Print the time since the post was pubished.
echo str_replace('mins', 'minutes', human_time_diff( get_the_time('U'), current_time('timestamp') ) . ' ago');
} else {
// Print the date and time the post was pubished.
echo get_the_time('F jS, Y');
}
Debugging in WordPress
- WordPress debugging mode displays PHP notices during development. It is strongly recommended that plugin and theme developers use WP_DEBUG in their development environments.
- Debugging in WordPress (codex.wordpress.org)
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
Prevent Automatic WordPress Updates
# Disable all automatic WP updates.
define('AUTOMATIC_UPDATER_DISABLED', true);
# Disable automatic WordPress plugin updates:
add_filter( 'auto_update_plugin', '__return_false' );
# Disable automatic WordPress theme updates:
add_filter( 'auto_update_theme', '__return_false' );
add_filter( 'automatic_updater_disabled', '__return_true' );
add_filter( 'auto_update_plugin', '__return_false' );
add_filter( 'auto_update_theme', '__return_false' );
add_filter( 'auto_update_translation', '__return_false' );
Reminders and Best Practices
Empty Your Trash
WordPress 2.9 introduced the WordPress trash system. Whenever content is deleted, be it a comment, post, page, media etc; it is sent to trash. From here, the content can either be restored or deleted permanently. It is effectively a fail-safe system that helps you recover anything that was deleted accidentally (in much the same way the recycling bin works in your computer). Trash can take up a lot of unnecessary room in your website’s database. The bigger the database, the longer it is to retrieve information from it. By default, WordPress will automatically delete trash after thirty days. This can be reduced by modifying the wp-config.php file. For example, you could reduce this to seven days by adding the following: define ('EMPTY_TRASH_DAYS', 7); You can completely disable the trash system by adding this to your wp-config.php file. define ('EMPTY_TRASH_DAYS', 0);
Monitor Your Plugins
Before you install any plugin on your website, ask yourself “Is this plugin necessary?”. Plugins are one of the biggest causes of WordPress websites being slow. The more plugins you install without research, the more likely you will face performance issues; however the sheer number of plugins you have installed is not the reason a WordPress website can slow down. Certain plugins are known for causing websites to be slow. There are many reasons for this including bad coding, calls to external servers and persistent calls and updating of your WordPress database. Pay close attention to how much CPU plugins use too. Many plugins can bottleneck your CPU due to persistent processes. If this happens, your whole server could go down. One plugin I highly recommend you use is P3 Profiler. Developed by GoDaddy, the plugin will show you exactly how much load time your plugins are adding. A breakdown is given which displays exactly how much load each plugin adds. It is the most effective way of seeing what plugins are slowing down your website.
Reduce Post Revisions, Drafts, Spam, Pingbacks and Trackbacks
It is not just trash that can needlessly increase the size of your database. All post types populate table rows with data. Therefore, it is important to regularly delete spam comments and unwanted pingbacks and trackbacks. You should also be wary of the number of drafts and post revisions your website has stored. The WordPress revision system allows you to go back to older versions of articles, view them and restore them. In addition to one autosave of your posts and pages, revisions will be generated each time you save your articles. This means that an article with ten revisions with take up ten times as much room on your database than the actual article that was published. As you can imagine, this increases the size of your database considerably. Post Revisions Post revisions can greatly increase the size of your database. By default, WordPress will save an unlimited number of revisions, however this is generally not needed. It is better to reduce this limit to something more practical such as two or three. You can do this by adding the following code to your wp-config.php file: define( 'WP_POST_REVISIONS', 3 ); Alternatively, you can completely disable the post revision system by adding the code below to your wp-config.php file. From a blogger’s perspective, this is not an optimal set up as post revisions are very useful, however many website owners have taken this step to ensure their database runs more efficiently. define( 'WP_POST_REVISIONS', false ); A more practical way of cleaning your WordPress database is to use WP Optimize. The plugin can automatically remove auto-drafts, spam comments, trackbacks and more. WP-DBManager is also a good solution for optimizing your database.
Choose Your Advertisements Wisely
Be conscious about the type of advertisements you add to your website. The most efficient way of promoting a product or service on your website (from a website performance perspective) is to link directly to the page using an image that has been optimized for the web. You can take this one step further and link using text links instead. Adding advertisements from third-party advertising networks can increase loading times due to the calls that are made to external servers. Even localised ad tracking scripts can hurt performance. For example, the popular ad rotation plugin OIO publisher has a bad reputation for increasing page loading times. Of course, advertisements are necessary for most websites to survive, therefore you need to strive for the right balance between speed and income. If you optimize all other areas of your website design, a few advertisements will not be too damaging. Just be sure you are fully aware of what load each advertisement adds to your website by testing your website speed before and after adding the advertisement.
Enable Gzip Compression
Gzip compression allows a website page to be transferred to a browser at up to 70% of its original size. The browser will then decompress the page and display it to the user. Gzip Compression Gzip compression is easy to enable in WordPress. Gzip can be enabled via the WordPress options page. You can find this page at www.yourwebsite.com/wp-admin/options.php. To enable Gzip, simply change the value of the Gzip field from 0 to 1.
Minify and Combine CSS and Javascript
Each call to your CSS and Javascript files is an HTTP request. This means that when someone visits your web page, their computer sends a request for a file and then the server sends it back. The more requests there are to your server, the longer it will take for your pages to load. The PHP5 application Minify combines multiple CSS and Javascript files into a single file. This greatly reduces the number of HTTP requests. The application also removes unnecessary whitespace and comments. There are a number of WordPress plugins available that will minify your CSS and Javascript files. I recommend using either WP Minify or Better WordPress Minify.
Enable Browser Caching
Some of the largest files on your website rarely change. This includes CSS files, Javascript files, your website logo etc. One way to take advantage of this is to enable browser caching. Browser caching allows internet users to speed up the loading time of their favourite websites by storing a cached copy of your website locally. This reduces calls to your server and saves the user from downloading the same files again. You can enable browser caching by adding the following code to your .htaccess file: ## EXPIRES CACHING ## <IfModule mod_expires.c> ExpiresActive On ExpiresByType image/jpg "access 1 year" ExpiresByType image/jpeg "access 1 year" ExpiresByType image/gif "access 1 year" ExpiresByType image/png "access 1 year" ExpiresByType text/css "access 1 month" ExpiresByType text/html "access 1 month" ExpiresByType application/pdf "access 1 month" ExpiresByType text/x-javascript "access 1 month" ExpiresByType application/x-shockwave-flash "access 1 month" ExpiresByType image/x-icon "access 1 year" ExpiresDefault "access 1 month" </IfModule> ## EXPIRES CACHING ## The code above specifies how long a particular file type should be stored. Files will simply be downloaded again if they have expired.
Install a Cache Plugin
Caching plugins allow you to publish static HTML files instead of dynamic files. This greatly reduces the time a page takes to load as there are no PHP or MySQL commands to execute. Additional caching features include minification, caching of feeds, Gzipping, Content Delivery Network (CDN) support, and much more. Caching your pages is one of the most effective ways of improving your page loading times, with many plugins promising an improvement of at least ten times. Popular caching plugins include WP Super Cache, W3 Total Cache and WP Fastest Cache. All three plugins are available free. W3 Total Cache W3 Total Cache is one of the most popular caching plugins available for WordPress.
Use a Content Delivery Network
Your website is hosted in a data center somewhere in the world. The further a visitor is from the location of your data center, the longer it takes for your web pages to load. Content Delivery Networks (CDN) address this issue by utilizing dozens of data centers around the world. They take the heavy work away from your hosting company by hosting your images, CSS and Javascript files, and serving these files to visitors from the closest location to them. Seconds can be taken away from your page loading times because of this. Popular content delivery networks include MaxCDN, Amazon CloudFront and CloudFlare. The cost of these services vary according to how much bandwidth your website uses. For example, MaxCDN’s cheapest plan costs $9 per month for 100GB of bandwidth.
Schedule Blog Posts for the Future
The majority of bloggers try to follow a publishing schedule. They post once a month, once a week or once a day. In WordPress, you can schedule posts to go live at a particular time and date, so you don’t need to be at your computer (or even awake) when the post goes live. Here’s how. In the WordPress backend, go to the Edit screen for the post you wish to schedule. 1. In the top-right of the page, look for a box titled "Publish," where you’ll find an option that reads “Publish immediately." 2. Click the blue “Edit” text next to “Publish immediately” and choose the month, date, year and time you want your post to be published. Remember to use military time (3:00 p.m. would be 15:00). 3. Click the gray “OK” button. 4. The “Publish immediately” text should now change to “Schedule for," with whatever date and time you have chosen. 5. If you’re ready to go, click the blue “Schedule” button (formerly "Publish"). Your post is set to go.
Use Analytics
You should never manage a site without some form of tracking. Google Analytics is free and so easy to implement that there’s no excuse not to use it.
Create a new analytics profile, and then install Google Analytics for WordPress by Joost de Valk. This plugin makes it easy for you to connect your profile to WordPress without the need to use copy and paste (and you can also enter the tracking code manually). Once connected, there are numerous settings that you should tweak at your discretion.
Additionally, you should ensure that you enable site search in your analytics profile.
Make it easy to find what’s in your library
If you own a library of books, does it make sense to house the books in separate buildings by the month they were acquired?
Of course not. You’d end up walking from building to building, searching for the book you wanted.
Your Media Library in WordPress is the same way. Creating one integrated folder where you place all your media makes it easy to search: just plug in a keyword and you’ll have the file you’re looking for in no time.
To set up your WordPress site so all your media files go into one folder that you can search by name, go to Settings & Media and uncheck the button next to “Organize my uploads into month- and year-based folders.”
Link between posts
Reference other post or pages within your site from your post.
Google Authorship
When you do a search on Google and see somebodies picture alongside the search results that is known as Google authorship.
Your content is linked to you even if you write it on another site
I love Google authorship because it’s not just good for branding it will also help your click through rate because your picture stands out.
In the example above Social Media Examiner have Google authorship implemented and as they have a multi-author blog so I get my image on the post for my guest post, yahoo!!!
When Google authorship is set up on your site if you look at the source code of your pages you’ll see something like this:
<link rel=”author” href=”https://plus.google.com/u/0/109282987970727189991″>;
XML Sitemap
An XML sitemap is like a table of contents in a book.
It provides a breakdown of the pages of your website and lets Google know how often this content is likely to change.
If you don’t have an XML sitemap Google will still crawl through your site to index your pages but it may miss some. For example, imagine if you had a page on your website that is not linked to from any other page on your website. This is a page that Google might miss.
If you build an XML sitemap this will include all the pages on your website that you want to index and it will provide additional information to Google such as how often you want Google to re-index the page. If it’s a static page that’s not going to change very often then maybe you only want to re-index it every couple of months!
http://wordpress.org/plugins/google-sitemap-generator/
In the image above you specify the page to be indexed, the priority (listed as ‘Prio’ in the table above), images on the page, how often you want it indexed and the date the content was last changed.
Action: Make sure you have an XML Sitemap. You can use the WordPress SEO plugin which will build one automatically or other XML plugins.
Bonus Point!! – If you have a lot of video on your site then it’s worth considering a Video Sitemap.
You are pointing Google to the Google + profile of the person (in this case it’s me). So Google picks up the image and details from this profile.
Action: Set up Google authorship on your blog. This can be done by manually linking your authors to their Google + page using rel=author or by using a plugin (e.g. WordPress SEO, Google author link etc).
Backup Your Website
Good backup practices are really important. What if your website is hacked or your server fails? Syed Balkhi recommends not simply relying on regular database backups either. Without all of your other data, such as images and plugins, your backup is incomplete. Syed recommends a service such as VaultPress or BackupBuddy. As Collis Ta’eed points out, you should “test regularly, and make sure you do a decent verification to ensure the backup is actually, completely, fully there and working. You don’t want to find out your backup wasn’t working… on the day you need it.”