WordPress Theme Development

WordPress themes are more than just the front-end HTML and styles of the website, a theme enables and defines specific WordPress features and controls the display of everything.

Common features which make WordPress what it is like Widgets and Menus are not enabled by default and require the theme to setup and configure them.

New functionality and filters for core functionality can be defined in the theme functions.php file. Front end WordPress templates can be used or completely re-imagined using the theme index.php file.

WP Theme Files

At the very minimum, a WordPress Theme consists of a uniquely named theme directory under wp-content/themes/ containing at least the two files style.css and index.php.

style.css file


The style.css file does not actually need any content but no two styles.css files can have the same content, so aside from being uninformative, an empty file is a bad idea. A WordPress file header (doc-block or comment) is the recommended way to list theme info. A basic style.css theme file could look something like this:

Theme Name: My New Theme
Author: Me
Description: Some new theme.
Version: 1.0

index.php file


The index.php file is the default template file for all front-end requests and is required for the theme to work.

WordPress Template Hierarchy

The WordPress Template Hierarchy is how WP defines what template file will be served for a specific request. If the specific template file for the request does not exist, the theme falls-back to the next available file. Child theme files fall-back to parent theme files. All template files eventually fall-back to the index.php file.

Bypass the Template Hierarchy

When developing an extendable theme for public distribution it’s best to stick to the WP Template Hierarchy. If the theme is not extendable, the Template Hierarchy can be bypassed with a custom theme router in the index.php file which is more organized, centralized, and allows for tight access control over the WP system.

The WordPress function get_template_part() can be used to include template files from custom sub-directories.

An example of theme routing using conditional tags in the index.php file:

 * Route the request to it's template file
 * WP is not provided any other template files so all requests go here.
 * This is done to control access to everything. Any route we want to block
 * simply becomes a 404 if it is not specifically defined here.
    if (is_front_page() && is_home())   { get_template_part('partials/default_home'); }
// elseif (is_front_page())             { get_template_part('partials/static_home'); }
// elseif (is_home())                   { get_template_part('partials/blog_page_home'); }
elseif (is_single() || is_page())       { get_template_part('partials/page_single'); }
elseif (is_search())                    { get_template_part('partials/page_search_results'); }
  else                                  { get_template_part('partials/page_404'); } // By default everything is a 404 page.

NOTE: When you use is_home() and is_front_page(), you have to use them in the right order to avoid bugs and to test every user configuration.

functions.php file

partial template files


404 partial page template


<?php get_template_part('partials/doc_top'); ?>
<h1>404 Page Not Found</h1>
<p>Sorry but the page you requested could not be found.</p>
<?php get_template_part('partials/doc_bottom'); ?>

WP Conditional Tags

WP function Returns true if:
is_404() The request returns an “HTTP 404: Not Found” error.
is_admin() The request is for the admin Dashboard or the administration panel.
is_archive() The request is for any type of archive page. An archive can be a Category, Tag, Author, Date, Custom Post Type or Custom Taxonomy based pages.
is_attachment() An attachment. An image or other file uploaded through the post editor’s upload utility. Attachments can be displayed on their own ‘page’ or template.
is_author() An author archive page.
is_category() A category archive page.
is_date() A year, month, or day
is_day() A day
is_feed() A syndication feed
is_front_page() When the front of the site should be displayed, whether it is posts or a Page. Returns true when the main blog page is being displayed and the ‘Settings > Reading ->Front page displays’ is set to “Your latest posts”, or when ‘Settings > Reading ->Front page displays’ is set to “A static page” and the “Front Page” value is the current Page being displayed.
is_home() The request is for the blog homepage. When the main blog home page should be displayed. This is the page which shows the time based blog content of your site, so if you’ve set a static Page for the Front Page (see below), then this will only be true on the Page which you set as the “Posts page” in Administration > Settings > Reading.
is_month() A month
is_network_admin() The request is for a network admin screen (wp-admin/network).
is_page() The request is for an existing single page.
is_post_type_archive() The request is for an archive page of a given post type(s).
is_search() The request is for the search result page.
is_single() A single post. Works for any post type, except attachments and pages.
is_sticky() The current post is a Sticky Post meaning the “Stick this post to the front page” check box has been checked for the post.
is_tag() The request is for a Tag archive page.
is_tax() The request is for a custom taxonomy archive page.
is_time() An hour, minute, or second
is_year() A year

WP Functions