Download today

WordPress Development for Intermediate Users: Theme Development in Detail

Interested in taking your WordPress game to a whole new level? Want to further develop your PHP skills and add more complex and exciting functionality to your themes and plugins?

Welcome to our latest series, WordPress Development for Intermediate users. This series follows on from our popular WordPress Development for Beginners tutorials, which introduced you to the fundamentals of developing websites with WordPress, how to get started coding with PHP, and building themes and plugins.

In this seven-week series, we step things up a notch to really test your skills. You’ll learn how to:

  • Develop a WordPress theme with include files, template parts, template tags, plus action and filter hooks
  • Add Customizer functionality to your theme
  • Develop plugins using best practice for coding
  • Add complex, custom queries and loops to your themes and plugins
  • Create and work with custom post types
  • Work with metadata, including post metadata (or custom fields) and other metadata e.g. author metadata, and
  • Translate your code and get it ready for release

When you’ve worked through this series and applied what you’ve learned, you’ll come out the other end a competent WordPress developer, ready to create your own themes and plugins and distribute them to other users or even sell sites built on them to clients.

Note: It’s important that you have a working knowledge of PHP as this is the foundational language of WordPress and I’ll be referring to code snippets throughout this series.

Let’s get started.

Before You Begin

This course assumes you have coded for WordPress before and that you have a basic understanding of how themes and plugins work. If you haven’t developed for WordPress before, or you’d like a refresher, I strongly recommend you read through WordPress Development for Beginners, which will give you everything you need to know before you start this series.

You’ll also need access to a few things so that you can follow along and work alongside me. These are:

  • A development WordPress installation. I recommend working on your local machine
  • A code editor with FTP access if you’re working remotely (which you will be doing eventually)
  • If your code editor doesn’t have FTP access, an FTP client

I deliberately haven’t given you links to help you find all these things – I’m assuming that you’re already at the level where you know about this kind of stuff and can find them yourself.

For this tutorial in this series as well as the next tutorials, we’ll be working with a demo theme that I’ve created, which you can find on Github. I’ve also created a demo site that I’ll be updating as we work through the series. Here’s how it looks right now:

demo site

As we work through the different topics in this part of the course, I’ll show you how to apply what you’ve learned to the demo theme. So if you want to follow along, download it before you start and install and activate it on your development site.

Take a look at the starting theme so you can see how it’s structured. It includes template files, widgets and a menu – all covered in our beginner development series. It also includes some basic styling – I’m not claiming that it’s beautiful, and you might want to improve on it!

What We’ll Cover in This Tutorial

In this first tutorial, we’re going to dive straight into theme development. This tutorial will build on what you learned if you studied the following modules in our WordPress Development for Beginners course:

So, I’m not going to show you how to create a basic theme or how to register a widget area or a menu. If you don’t know how to do these things, go back to that series and check it out!

Instead, we’re going to look at more advanced aspects of theme development, specifically:

  • Approaches to theme development
  • Structuring your theme – the template hierarchy
  • Using template parts
  • Adding template tags for styling
  • Adding functionality in the functions file
  • Adding hooks to your theme

But before we start coding that, let’s take a look at some of the approaches available for theme development.

Approaches to WordPress Theme Development

Before you start to develop your own themes, it’s worth considering how you’re going to go about it. Let’s take a look at some of the possible approaches.

Approach 1: Coding from Scratch

Writing a theme from scratch isn’t something I’d recommend. It means starting with a blank PHP file (or files) and then adding all of the code you need to create a theme. You might decide to do this the very first time you build a theme but you certainly shouldn’t do it for subsequent themes. After all, there will be a lot of shared code that you can re-use.

So, whatever approach you use for your first theme, don’t code your next theme from scratch – either edit your first theme, or use your first theme to create a starter theme.

Approach 2: Adapting Static HTML

This has traditionally been the method that people use to learn WordPress, and it’s a good approach if you’ve already created static sites and are comfortable with coding HTML. Alternatively, if you’ve created a prototype for the site you’re building using static HTML, this might be the approach you use.

If you’re starting with static HTML, you’ll need to do a few things to convert your markup to a theme, including:

  • Changing your index.html file to index.php
  • Splitting it into template parts – separating out the header, footer and sidebar into different files
  • Adding a loop instead of static content
  • Adding any relevant template tags (more of which shortly)
  • Editing information in the <head> and elsewhere on the page, such as site name and page description. Use functions such as get_bloginfo() to fetch this from the database instead of manually coding it into your theme
  • Replacing a hard-coded navigation menu with one that uses the WordPress menus interface
  • Replacing static content in the sidebar and footer with widget areas, where relevant
  • Adding extra template files as well as index.php – more of which shortly

You’ll have learned about a lot of this in our beginner WordPress development course.

For a detailed walkthrough that teaches you how to create a theme from static HTML, you might find my book, WordPress Theme Development: Beginner’s Guide, helpful.

Underscores is a starter theme that can speed up your WordPress theme development
Underscores is a starter theme that can speed up your WordPress theme development

Approach 3: Using a Starter Theme

Another approach is to take a third-party starter theme such as underscores and use that as the basis for your code. This will give you all the WordPress essentials such as a loop, and save a lot of work.

Alternatively, you can use your own starter theme, that you create when you develop your first theme. Strip out all of the code that won’t apply to other themes, such as colors, fonts or bespoke layout and functions, and use that to kick things off when you develop your next theme.

Make sure your starter theme is coded using DRY principles and that it’s responsive (or even better, mobile-first) and includes accessibility features.

If you have extra functionality that you add to a lot of your themes but not all of them, you could keep include files for each of these and then add them to a theme when you need to. I’ll show you how to do this later on in this part of the course.

Approach 4: Creating a Child Theme

Another way to code your themes is by using an existing theme as a parent theme and then creating a child theme of that for each project. I work in a way that combines this and the starter theme approach: I’ve created my own custom framework theme, which I use as a parent theme for every new site I build, and a starter child theme with just a few basics in it. I then add to and edit that child theme for each project.

Using a child theme means you can keep all of the code you use again and again in your parent theme, saving you time and server space. If you need to override anything, just create a template file with the same name in your child theme, and WordPress will use that instead of the one from the parent theme.

You might also use a third party theme as your parent theme, such as a framework theme. Many frameworks come with child themes you can use out of the box, but there’s nothing to stop you coding your own.

cherry framework website
A theme framework like Cherry is one way to approach developing your own child themes

Approach 5: Customizing an Existing Theme

A popular approach when people are first starting out is to take an existing theme (such as the default theme, currently Twenty Sixteen) and customize that to meet your own needs. This can be a good way to get started as it lets you pore through the theme’s code to see how everything works and can be a great way to learn. However there are some caveats:

  • If you want to benefit from updates to the theme, use a child theme instead of directly editing the theme
  • You may find yourself stripping out a lot of functionality and styling and adding your own
  • Only use a theme that is similar to what you want to achieve
  • Only use a well-coded theme – check out its reviews in the WordPress Theme Directory

In short, if you’re using a third party theme as a way to learn and plan to tear it apart to create your own, and you’re not worried about updates, then go ahead. But if you’re going to change so much that it’s unrecognizable, a starter theme may be better. If you want to keep a lot of the styling and functionality from the theme, use a child theme to make your own tweaks.

Theme Structure: The Theme Template Hierarchy

Your theme will need to include certain template files, which are the files WordPress uses to display content depending on what page a visitor is looking at. There are four main types of file in your theme:

  • Template files – index.php, page.php and more
  • A stylesheet – style.css
  • Template parts – header.php, sidebar.php, footer.php and any other template parts you create, such as a loop.php file
  • Functions files – functions.php and any include files

The minimum number of files is two: index.php and style.css. Theoretically, you could build a theme with just these two files, but I wouldn’t recommend it. Separating out things like the header and footer and creating different template files for static pages, archive pages and single posts, for example, will make your life easier. And using include files can make your code more efficient.

Our starting theme includes the following files:

  • index.php
  • style.css
  • functions.php
  • header.php
  • sidebar.php
  • footer.php

This is one template file, one stylesheet, one functions file and three template parts. I’ll explain what each of these are in turn.

Template Files

The first file WordPress goes to when displaying content is the relevant template file. It will pick this according to what content is being displayed, using the template hierarchy. - visual guide to the template hierarchy is a great interactive guide to the theme template hierarchy

So, for example, if a visitor is reading a single post from your blog, WordPress will work through this list of files and use the first one it finds from this list to display content:

  1. single-post.php (for single posts, not pages or custom post types)
  2. single.php (for single posts or custom post types, not pages)
  3. singular.php (for single posts, custom post types or pages)
  4. index.php (for anything that doesn’t have a more specific template part)

And if your user navigates to an archive page, for example the archive for the “Featured” category, WordPress will work through these template files:

  1. category-featured.php (just for that category)
  2. category-XX.php (where XX is the ID of the ‘featured’ category)
  3. category.php (for all category archives)
  4. archive.php (for all archives including categories, taxonomy terms, authors and tags)
  5. index.php

So as long as your theme has an index.php file, there will always be a file available to display content. But you need to make sure it accounts for all content types, including single posts and pages, archives and search pages, as well as the 404 page. It can be easier to create template files specifically for each of these.

Let’s add a couple more template files to our starter theme to customize the way the theme displays single posts and pages. The easiest way to do this is by copying the index.php file. First, let’s do this for pages.

  1. Make a copy of index.php and call it page.php.
  2. Find the following line:
    .gist table { margin-bottom: 0; }
  3. Edit it so it reads as follows:
    .gist table { margin-bottom: 0; }
  4. Save your new file.

This doesn’t change much when people are viewing the site, but it does leave out some code that isn’t necessary. The conditional statement you removed checks if we’re on a page, something that isn’t necessary as WordPress will only use this template file if we’re on a page.  It also changes the h2 tag to h1.

Now that you’ve done this, you can edit the index.php file to amend that check for the front page.

  1. Open index.php.
  2. Find this code:
    .gist table { margin-bottom: 0; }
  3. Edit it so it reads like this:
    .gist table { margin-bottom: 0; }
  4. Save the file.

This removes the check for the front page from the loop.

Now let’s create a file for single posts.

  1. Make a copy of index.php and call it single.php
  2. Find these lines:
    .gist table { margin-bottom: 0; }
  3. Edit them so they read as follows:
    .gist table { margin-bottom: 0; }
  4. Save the file.

This removes the check for being on the front page, as a single blog post won’t be the front page. It also changes the h2 tag to h1.

Finally, let’s create a fourth template for archives.

  1. Make a copy of index.php and call it archive php.
  2. Find this line:
    .gist table { margin-bottom: 0; }
  3. Underneath it, add these two lines:
    .gist table { margin-bottom: 0; }
  4. Save the file.

The Stylesheet

Every theme must contain a stylesheet, because that tells WordPress about the theme, as well as providing styling for your site.

Your stylesheet needs to contain commented out text at the top telling WordPress all about it. In the theme we’ll be using, the stylesheet starts with the following:

.gist table { margin-bottom: 0; }

Template Parts

If you’re creating lots of template files, each with its own loop, header, footer etc., you may be worrying about all the repeated code. The good news is you don’t need to repeat any code. You can use template parts to code certain parts of your theme just once and then include that code in your template files. Examples include:

  • The header – header.php
  • The sidebar – sidebar.php
  • The footer – footer.php
  • A generic loop – loop.php
  • A more specific loop – loop-page.php, for example

Let’s use a template part for the loop in our theme.

  1. Open the index.php file.
  2. Find this code:
    .gist table { margin-bottom: 0; }
  3. Copy that code.
  4. Create a new file in your theme called loop.php.
  5. Open your new file and paste the code into it. Save the file.
  6. Go back to index.php and delete the code you just copied.
  7. In its place, add this:
    .gist table { margin-bottom: 0; }
  8. Save your file.
  9. Now delete the code above from the archive.php file and replace it with the same get_template_part() function as you’ve used in loop.php. Save the archive.php file.

Now, instead of having the loop coded into two template files you’ve got it in one file. If you need to edit it you only have to do so once.

Let’s do the same for the loop for single posts and pages.

  1. Create a new file in your theme called loop-single.php.
  2. Open the page.php file.
  3. Find this code:
    .gist table { margin-bottom: 0; }
  4. Copy it into your new include file and delete it from page.php.
  5. In page.php, replace it with this:
    .gist table { margin-bottom: 0; }
  6. Save your files.
  7. Now repeat the above for single.php, removing the loop and replacing it with the function.

Again this uses the get_template_part() function, but this time it has two parameters: “loop” and “single.” If WordPress can’t find a loop-single.php file, it will fall back to using loop.php.

Functionality Files

If you want to add functions to your theme, you should use functions.php. This is where you’d do things like registering widgets and menus. If your theme starts to contain a lot of functionality and you want to separate it out, you can use an include file. We’ll do this in the next post in this series, where we’ll add an include file for Customizer functionality.

To include a file, you add something like this to your functions.php file:

.gist table { margin-bottom: 0; }

This includes a file on the includes folder in your theme, called customizer.php. The code from that file is run as if it were coded into the functions.php file at the point where you placed the include function.

Our theme already has a file called functions.php which contains the functions for registering menus and widgets. Let’s add some theme support to it.

  1. Open functions.php
  2. At the bottom, add these lines:
    .gist table { margin-bottom: 0; }
  3. Save your file.

You’ll now find that when you add posts to your site, you can set featured images and specify post formats. For more on using functions.php for theme support, see our ultimate guide to the theme functions file.

Challenge: Adding More Template Files

Now that you’ve added some files to your theme, try adding some more without my guidance. Add the following files:

  • 404.php – for error pages
  • search.php – for search results

You might want to use a copy of archive.php for the search template, and a copy of any of your files for 404 pages, but replacing the loop with an error notice. Even better, you could include a list of the most recent posts and/or a search box in your search page – something we’ll do later on in this course.

If you get stuck, take a look at the finished part 1 theme from the source files for this series.

Adding Template Tags to Your Theme

The next step is to add some template tags to your theme. Here’s how the WordPress Codex defines template tags:

Template tags are used within your blog’s Templates to display information dynamically or otherwise customize your blog, providing the tools to make it as individual and interesting as you are.

Template tags are a kind of function, but instead of using them in a functions file or a plugin, you use them in your template files to generate content such as:

  • Fetching content from template parts with get_header(), get_sidebar(), get_footer() and get_template part().
  • Displaying information about the site such as its title, home url or description using bloginfo().
  • Outputting post content and metadata with tags like the_content(), the _title() and the_permalink().
  • Displaying information about a post’s author with tags like get_the_author() and get_the_author_link().
  • Outputting information about the post as an ID or class for styling purposes with tags like body_class().

Note that some tags have a get_ at the beginning of them while others don’t. If you use a tag that begins with get_, all WordPress does is fetch that information – it doesn’t output it. So to output what you’ve fetched, you use echo before it. For example, echo get_the_author_link() echoes out the link to the author’s profile. This gives you more control over exactly how content is output. If you just used the_author_link(), WordPress would output this in a predefined way. Sometimes that works for you, but sometimes it doesn’t and you want to add your own markup around a template tag with get_ at the beginning.

The theme we’re working with already has some template tags added. Work through the template files and see if you can find them. You should find the following:

  • In header.phpbloginfo('url')bloginfo('name') and bloginfo( 'description' ).
  • In index.php, archive.php, single.php and page.php: get_template_part(), which you added earlier.
  • In loop.php and loop-single.php: the_permalink()the_title_attribute()the_title() and the_content().

So you can see you’ve already been working with template tags. Let’s add some more, specifically to help with styling.

Adding Template Tags for Styling

WordPress gives you three incredibly useful template tags that you can add to your <body> element and to your loop to enable more fine-grained styling of your posts, pages and archives. These are:

  • body_class(), which you add to the body tag in a theme’s header.php file: it adds classes to the body element according to the type of page being viewed
  • the_ID(), which you can use to add the post ID to a post in the loop
  • post_class(), which works in a similar way to body_class() but is used with posts in the loop

Let’s add them to our theme.

  1. Open the header.php file.
  2. Find the opening <body> tag, which is on its own line.
  3. Edit it so it reads like this:
    .gist table { margin-bottom: 0; }
  4. Save and close the file.
  5. Open the loop.php file.
  6. Find the opening <article> tag which will be on its own line.
  7. Edit it so it reads:
    .gist table { margin-bottom: 0; }
  8. Save and close the file.
  9. Repeat steps 5-8 for the loop.php file.

You’ll now find that your <body> element has a number of classes assigned to it, depending on what kind of content is being viewed. And your <article> elements each have an ID which is the post ID and a number of classes relevant to the kind of post it is.

Let’s take a look at the code that’s generated for the home page of the site. Save your theme and go to your site’s home page in your browser. Inspect the code. Here’s mine:

inspecting code on my site's home page

This is the code that’s output:

.gist table { margin-bottom: 0; }

Now let’s take a look at another page. Navigate to a single post and see what’s output for the body:

.gist table { margin-bottom: 0; }

As you can see, WordPress generates different classes because we’re on a single post. Now take a look at the code that’s generated for the <article> tag on that single post page:

.gist table { margin-bottom: 0; }

The article has a number of classes which indicate the post ID, its post type, status, category and more, as well as an ID equivalent to the post’s ID. You can then use this to style your posts according to category or post type, or even individually by targeting the post ID. So if you were running a news site for example, with each category having its own color, you could style all posts in that category using the appropriate color on the main listing page.

Adding Filter and Action Hooks to Your Theme

The next thing you can add to your theme to make it even more powerful are hooks. These let you either amend the content you already have in your theme or add new content, without editing the template files themselves. So if you wanted to write a plugin that inserts content somewhere in your pages, you could do this easily. In fact, we’ll do this later on in the course.

It’s also a really useful technique if you’re developing a theme that you intend to use as a parent theme. In your child theme’s functions files, you can create functions that insert extra content as required into the parent theme (or amend existing content) without creating duplicate template files in your child theme. All theme frameworks have a large number of hooks so you can do this.

If you want to understand how hooks work, and the difference between action and filter hooks, you need to study part 5 of our WordPress Development for Beginners series, which shows you how to use hooks in your plugins. So in other words, you should already know this!

Here, we’ll be doing something a bit different: Instead of writing a function to hook to an existing hook, we’ll be creating that hook in our theme.

Adding Action Hooks

To create an action hook in your theme you use the do_action() function. This has one parameter: the unique name of the hook.

So let’s use this to add some action hooks.

  1. Open the header.php file.
  2. Immediately above the <header> tag, add this line:
    .gist table { margin-bottom: 0; }
  3. Now immediately below the closing header tag which reads </header>, add this line:
    .gist table { margin-bottom: 0; }
  4. Save and close the file.

You’ve just added two action hooks to your header. You could use these to add extra content there in your theme’s (or a child theme’s) functions file or via a plugin. Now let’s add some more.

  1. Open the index.php file.
  2. Find the <div class="content"> line and add this immediately below it:
    .gist table { margin-bottom: 0; }
  3. Now immediately before the closing </content> tag, add this:
    .gist table { margin-bottom: 0; }
  4. Save and close the file.
  5. Repeat steps 1-4 for single.php and page.php.

You’ll have noticed that you’ve added the same hook three times in three different files. If you wanted to, you could change the structure of your files, maybe moving the opening markup from index.php, page.php and single.php into header.php, and the closing markup into sidebar.php. If you want to try this, please go ahead, but be careful that you don’t miss anything out.

The advantage of using the hook, even though we’ve had to add it three times, is that if we wanted to add extra code before or after the content, we only have to do it once, via a function that we then attach to that hook. The function would run regardless of which of the three template files WordPress is currently using. And if you only want to hook new content to one of your template files, you could use a conditional tag to check what kind of content is being viewed. Again you’ll learn this later in the course.

Next let’s add a hook to each of the sidebar and footer. I’m not going to give you detailed instructions here, instead I’ll let you work it out for yourself. If you get stuck, check the source code for this part of the course. In that source code I’ve included both the starter theme and the finished theme.

So, add these hooks:

  • wpmu_before_sidebar before the sidebar widget area (making sure you put it outside the conditional tag for active widgets.
  • wpmu_after_sidebar after the sidebar widget area.
  • wpmu_before_footer before the footer.
  • wpmu_after_footer after the footer.

You’ll need to edit two files: sidebar.php and footer.php. Make sure your hooks are inside the <aside class="sidebar"> and footer elements.

Adding Filter Hooks

Filter hooks let users amend what’s output by the theme, overriding the content you’ve coded into it. A useful place to do this is in the header, where the site title and description are. By doing this you give users the option to replace these with a logo, for example.

So let’s do it!

  1. Open the header.php file and find this code:
    .gist table { margin-bottom: 0; }
  2. Edit it so it reads:
    .gist table { margin-bottom: 0; }
    Don’t forget to change all the instances of bloginfo() to get_bloginfo(), because of the echo that surrounds the whole thing. And make sure you’ve got all the syntax right – PHP is very unforgiving when it comes to semicolons!
  3. Save the file.

This doesn’t make any different to what’s displayed in the header yet, but if someone using a child theme or writing a plugin should want to change this specific aspect of the header in future, they won’t have to create a duplicate of the whole header.php file. All they need to do is write a function which they attach to that filter hook using add_filter(). We’ll take a look at doing that later in the course.

Theme Building is Fun!

Now that you’ve completed this part of the course you’ll know a lot more about theme building, and you’ll have the beginnings of your own theme with some powerful features that you can use to develop the theme further and add content to your site.

I haven’t included CSS in this series as it’s about WordPress, not CSS. But if you want to add or change the CSS in the theme’s stylesheet please go ahead – I’d love to see how you style my basic starter theme and make it look better!

If there are any items that you’ve struggled with when it comes to adding the code to your theme, or you want to see how I’ve done it, check out the files for the part 1 completed theme in the source files for this series. I strongly recommend doing this before posting questions below, as the best way to learn theme building is by interrogating the code.

In the next tutorial in this series, we’ll continue working with this theme and we’ll add theme Customizer functionality to it.

Related Posts


Submit a Comment

Your email address will not be published. Required fields are marked *