1. Code
  2. Theme Development

Developing Your First WordPress Theme: Day 2 of 3

Read Time:20 minsLanguages:
This post is part of a series called Developing Your First WordPress Theme.
Developing Your First WordPress Theme: Day 1 of 3
Developing Your First WordPress Theme: Day 3 of 3

Themes are a huge part of what makes WordPress as popular as it is, and in this three-part series we'll take you through a step-by-step process that results in a completed, functioning WordPress theme. In part two, we delve into coding the bulk of our theme!

Looking for a free WordPress theme to get started fast? We have some great ones for you to choose from!

Part Two

Welcome to part two of this three-part series on developing a WordPress theme from scratch. Last time we looked at what makes a "good theme", as well as the general components required for a theme to work. This week we're going to dive straight in and start creating our very first theme.

Our Theme

I'd like to stress that if you have your own layout to work with, use it - chances are you'll learn more by experimenting and you'll have a result that will be tailored to your tastes. If you don't have a layout to work with, we're providing a simple personal layout for you to work with.

This layout is something I made a while back as one of many unused designs for a friends personal blog. In the downloadable zip that accompanies this tutorial, you will find two folders; bftheme and bffiles. In the bffiles folder is the layout in its pre-WordPress state, the other folder contains the completed theme.

Open up the theme in a browser to get an idea of what we're going for, it should look a little something like this:

Breaking It Up

While it would be possible to make a theme work with just one file, it's very bad practice and not something you'll see at all in the wild. It's good to stick to the standard file structure as it makes theme modification easier down the line and lets you use the built in WordPress functions to include files easily (such as get_header()).

First of all, let's prepare our workspace. In the themes directory of your WordPress installation, create a new folder called blindfaith. Inside that folder, create the following files:

  • index.php
  • single.php
  • page.php
  • comments.php
  • functions.php
  • header.php
  • footer.php
  • sidebar.php

Now we've got our stylesheets and images in place as well a theme skeleton, we're going to jump right in. First we need to make our theme appear in the WordPress dashboard - to do this we need to modify our style.css file.

WordPress will automatically look for a file called style.css in a theme directory to extract information about the theme. Paste the following code in to the top of style.css:

If we check WordPress now, our theme should appear in the change themes part of the dashboard. Activate our new theme and load up the front page of WordPress. Seeing nothing? Good. Once WordPress has done its magic figuring out what page the user wants and has prepared the results, it calls index.php from our theme directory - except right now that file is blank.

First of all, we need to cut up our HTML in to its four respective parts; header, body, sidebar, footer. If you open up the index.html supplied with this tutorial, you should see this:

If we load up this HTML in a browser at the moment, we will see the basic layout. Looking at this layout, the first thing we need to do is decide what the header should include. Since we want the title, search box and navigation at the top of every page, that's what we will put in to our header file.

The main content area will be variable, meaning it could be index.php, page.php, etc. The sidebar is all the content outside of the content box to the right of the layout and the footer will simply be the copyright message. Our theme will be made up like this:

So, copy the code from index.html all the way from the doctype to the content division and paste it in to our header file, we should now have a header.php file that looks like this:

For now, we will skip the content section as that is the biggest and most complex part (made up of many different files) and move straight along to the footer. Usually a footer comes last in a layout, however since the sidebar comes after the footer in our code, we will simply call sidebar after footer. Therefore footer.php should contain the following code;

You'll notice that we're using our first WordPress function above; get_sidebar();. This function is roughly the same as require(“sidebar.php”); and since we're going to always require the sidebar after the footer, it makes sense to call the sidebar in the footer file at the end.

Finally we need to include the sidebar. Since the footer comes before the sidebar, the sidebar is the last file included and so should close the design too (by closing the remaining tags; wrapper, body and html).

For now, open up index.php and enter the following;

If we navigate to our installation of WordPress, we should get something like this

At the moment, the website content (or what we've done so far) seems to be loading but the stylesheets are not. This is because in our header file, the calls to the stylesheets now use a path that does not exist. They now reside in /wp-content/themes/blindfaith/, but there's an easier way of pasting that everywhere it's needed - a more dynamic way.

The bloginfo() Function

WordPress comes with a built in function called bloginfo() that's great for getting all sorts of useful local information such as; blog name, description, stylesheet URL, stylesheet directory and more. For more information on what we can get with bloginfo, read this page in the WordPress codex.

Let's open up our header file and change a few things to use the dynamic information provided by WordPress rather than the static information in the theme. Our current header.php file looks like this up until the nav-bar-tile tag:

First of all, let's fix the missing stylesheets. We'll use two values from bloginfo; stylesheet_directory and stylesheet_url. The URL value is a direct link to style.css, whereas directory lists the directory style.css resides in. It's important to remember that WordPress functions like this do not append a trailing slash to values.

Replace the stylesheet lines with the following;

Our theme now has properly linked stylesheets. Next up, whilst we're in the header file, let's change the blog title, slogan and link.

The <title> tag doesn't simply have the bloginfo property that represents the name of the blog, we can also add another function; wp_title(). This function returns the title of the page or post currently being viewed, prepended with ». To turn off the » before the page name, simply change the parentheses of wp_title() to wp_title(“”, true);

This will produce something along the lines of;

Now we can simply change the logo/title text, slogan and URL using the following bloginfo() properties;

Our page should now look something like this;

Now we'll take a look at the index.php file. This is the file called by default and should be able to display lists of posts for the front page, categories, archives and search results - or an error message if none exist. Obviously each one of these different lists can contain variable amounts of posts, we can work with this by using something in WordPress known as "The Loop".

The Loop

WordPress figures out what posts to display before the index file is executed — after all we are making a theme, and the theme comes last as it's simply a way of displaying output. Using some in-built functions, we can avoid having to do complex PHP loops with constant checks for valid data - this aspect of WordPress theme development makes the process a lot easier and causes less headaches.

First of all, let's look at our post structure;

Since we know what the structure of a post looks like and we have a copy with dummy information, we can replace the dummy information with some functions that will return actual post values. There are several pieces of information we can display with each post, such as;

When any one of these functions is called within the loop, they display the correct information for the current post being looped through.

Using the link above (or just the functions supplied before the link), try to replace the dummy content on your own with the correct replacement functions before carrying on.

The correct code should look like this;

There are a few bits you may not have been able to do, let's look at them.

First of all, when displaying categories, WordPress likes to print a default style using a list. To override this, we can provide our own separator, which in our case is simply a comma and a space.

Next up to display an edit link, followed by how many comments a post has, we can use a function that creates the link and can output three different states for; no comments, single comment and multiple comments (where the percentage sign is the placeholder for the comment count).

Finally we have a simple if statement to decide what type of content to show. If we use the_excerpt() then only an excerpt of the content is shown, if we use the_content() then all of the content is shown (or until a <--more--> appears in the content). On a search or archive page, it isn't important to show the full article - just enough to get the gist - so we use the_excerpt().

Now in order to make this code work, we have to supply it with posts, and to do that we need to put it inside the loop. Our index.php file should currently resemble this;

Put this code after the header function;

and this one just before the footer function;

Loading up the WordPress blog should now look something like this;

Now our theme will show a list of WordPress posts according to how many should be displayed (changed under general settings in Dashboard). But what if there are more posts? What if the blog contains 6 posts but only displays 5? To combat this we need to add simple next/previous or new/old links.

Of course there's no point displaying these links if there are no newer or older posts to jump to as it's misleading, therefore we will use the following code after the loop;

The next_posts_link() and previous_posts_link() will only display when they are needed, using the text provided in the first parameter. Of course it is possible to remove the if statement and only use the following two lines;

But using the if statement above, we have the option of showing a message if there are no pages to skip to, which can make things less confusing for the user (which is always a good thing).

Our completed index.php file should look like this;

Single Posts

We now have a working index, but now we need a way to display single posts. Due to the simplicity of our design, our single.php file and index.php are near identical, the difference being that we don't need next/previous links in single.php but we do need comments. The code for single.php is as follows;

As you can see, not much has changed except around the bottom of the file. We've simply removed the code for the links and added a new function called comments_template(). The parameters for this function are simply the file to load (comments.php if left blank or by default) and whether or not to sort comments by type (default to false).

As you've probably guessed, the file that handles comments is comments.php - it is kept in a separate file so we can use it on both single.php and page.php alike.


The file for displaying a page is almost identical to the single post file with the exception that information about time of post, author and so on is removed. This means the page file looks like this;


The final part we'll be adding today is the navigation up top (as it's so simple)! Open up header.php and replace the nav-bar-tile division with this;

The wp_nav_menu function spits out a list of pages, however it also takes arguments in the form of an array. The arguments we have supplied, in order, are;

  • menu - The desired menu
  • menu_class - The CSS class to be used
  • menu_id - The UL element ID
  • container - Whether or not to wrap the list
  • theme_location - The location of the menu within the theme (for multiple menus)
  • show_home - Whether or not to display a 'Home' link

The CSS we're using is coded to adapt to the way WordPress spits out a navigation list, it's important to consider how a list will be outputted in code by WordPress when coding a design.

Our WordPress installation should now look like this;

Next Time...

Next time we will look at adding a functional sidebar that's widget ready, dynamic post types, custom fields and wrapping up the final few elements in the theme!

If there is anything you were unsure of in this post, or if you just have questions, feel free to leave a comment below. For those with questions or just those wanting to know more, the WordPress Codex is goldmine of information for all the functions and so on that WordPress uses.

Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.