Feb
How To Create A WordPress Theme - Part 3
by admin
In this part we shall be converting the index.htm file, that was created in How To Create A Wordpress Theme - Part 2, into a Wordpress compatible file. This involves adding a number of PHP functions and adding a file or two.
I shall briefly describe the functions as we go along, but really you will need to have a look at the freely available reference material. Most of the reference material you need is at Wordpress.org. So I shall not repeat it all here, just enough so that you know what you’re doing and why.
What is PHP?
PHP stands for "PHP Hypertext Preprocessor", which probably doesn’t mean a lot to you. In essence, PHP is a scripting language that allows you to write blocks of code that will do useful things for you. A major use is in creating web pages that are dynamic.
This means that instead of writing 100’s of page that are the all the same except for the actual content, you can write one page that accepts the content from a database by using a few variables. If you want to read up on PHP the main reference site is www.php.net.
Anatomy Of A Theme
According to Wordpress.org the bare minimum of files needed for a theme are:
- index.php
- style.css
If you look in any themes folder there is usually more than just one php file, you will see a lot more than that. But as this is a tutorial we will start of easy by changing the index.htm file you created last time into an index.php that is compatible with Wordpress.
To make it compatible you shall change the extension from htm to php and then add the functions required by Wordpress. What is a function? you ask. If you had a series of lines of code that calculated something and these lines of code were used several times within a page, it would make for a large file size.
A function allows you to take those lines of code and give them a name. This way, instead of having to type all those lines you just type the name you have given them and the code is executed. In PHP a function looks like:
function function_name (parameter_list) {
Statement
Statement
return value
}
function_name: This is it’s name, no spaces allowed.
parameter_list: You can give a function one or more parameters to work on. For example if you wrote a function to multiply any two numbers it might look like:
multiply (6, 4);
Statement: this is a line of code. You can have one or more lines of code in a function.
return value: This takes the value you have calculated and sends it back to the main code. An example of usage would be:
x = multiply (6, 4);
An example function would look like:
function halfsquare (mynumber) {
x = mynumber * mynumber;
x = x / 2;
return x;
}
This function would take your number mynumber, square it and then half it and return the result.
Note: Functions can also return text.
Requirements
As we are dealing with a PHP you WILL need a web server. For this tutorial I am using WOS which allows you to create the web server on a memory stick so that you can work anywhere there is a system with either WinXP or Vista.
To edit the files you could use NotePad, but a dedicated editor is better. For this tutorial I am using HTML-Kit, it is free and easy to use.
Preparation
- Startup your web server.
- Startup HTML-Kit.
- Load index.htm.
- Save as index.php.
Throughout this tutorial I shall be referring to line numbers in index.php. These line numbers are from the page that was developed in How To Create A Wordpress Theme - Part 2 where you can download the original files needed.
We are now ready to start editing…
The Style Sheet
Before Wordpress can "see" your theme you will need to add some comments at the start of your style sheet as follows:
/* Theme Name: My Theme Theme URI: http://www.ageeksjourney.com/wpthemes/ Description: Used in the create a theme tutorial at http://ageeksjourney.com Version: 0.1 Author: Colin King Author URI: http://www.ageeksjourney.com/ */
These eight lines MUST be at the start of style.css in every theme you make. Most of these lines are self explanatory except for:
Theme URI: this is where the finished theme can be downloaded from. For the purpose of this tutorial you can enter any URL you want, but remember to change it if you do offer the theme for download.
Description: Whatever you enter here will show on the Presentation tab in the Wordpress Admin Panel.
Save the edited style.css. Now you can open your browser and go to the Admin Panel for Wordpress at:
http://localhost/wordpress/wp-admin/
Click on the Presentation tab and you should see your development theme, click on it. Then you can go to :
http://localhost/wordpress/
This will show you what your theme looks like. Horrible isn’t it? The reason is because it cannot find the style sheet. To rectify this, change line 7:
<link rel="stylesheet" type="text/css" media="screen" href="style.css" />
To:
<style type="text/css" media="screen">
@import url( <?php bloginfo('stylesheet_url'); ?> );
</style>
Save index.php and refresh the browser. You will see that most of theme is now visible.
The Head Section
Change line 3 (starts with <html) to:
<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
Change line 5 (starts with <meta) to:
<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php
bloginfo('charset'); ?>" />
After line 9 ( </style>) add:
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="<?php bloginfo('rss2_url');
?>" />
<link rel="alternate" type="text/xml" title="RSS .92" href="<?php bloginfo('rss_url'); ?>" />
<link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="<?php bloginfo('atom_url');
?>" />
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
<php wp_head(); ?>
These lines enable the different rss feeds, the pingback and other functions needed by Wordpress.
The last line to change in the head section is the title tag. This determines what will show in the browser’s title bar and search engine listings. If you look at the default themes you will see:
<title><?php bloginfo('name'); ?><?php wp_title(); ?></title>
This will print the blog’s name followed by the post’s title. This is not very SEO friendly. If anything you should swap them around so that the post’s title is first. Also if you are on the homepage there is no post title so you could have the blog title followed by the tag line. You could solve the problem by using a plugin, but other’s may not want to. The theme should work without plugins.
If you do a search for "wordpress title tag" you will see a number of solutions. Here is one solution you could use:
<title>
<?php if(is_single()) { ?> /* Is it a single post page? */
<?php } ?> <?php wp_title(); ?> /* Yes, print the post title */
<?php if(is_404()) { ?> /* Is it a 404 page? */
» 404 Error! Page Not Found /* Yes, print a message */
<?php } ?>
<?php if(is_search()) { ?> ?* Is it a search result page ? */
» Search Results for: <?php echo wp_specialchars($s, 1); ?>
<?php } ?>
<?php bloginfo('name'); ?> /* In all cases print blog's name */
<?php if(is_home()) { ?> /* If it is the homepage */
» Home Page /* Print homepage */
<?php } ?>
</title>
I have included comments to explain the code, do not type them in. This code replaces line 15:
<title>Untitled</title>
The Page Header Section
Looking at the page in the browser the two images are missing, this is easily fixed by adding:
<?php bloginfo('template_url'); ?>
to the img tags like this:
<img src="<?php bloginfo('template_url'); ?>/images/toprss.jpg" alt="subscribe to rss" />
and
<img src="<?php bloginfo('template_url'); ?>/images/title.jpg" alt="My blog name" />
This will get the page to look right, but in the head and navigation area there are links that are currently just a #, these need replacing. Lines 34 and 35 are two links for people to subscribe to the post’s rss feed:
<a class="subrss" href="#">
Both lines are replaced by:
<a class="subrss" href="<?php bloginfo('rss2_url') ?>">
If you want to subscribe to comments instead, then use:
<a class="subrss" href="<?php bloginfo('comments_rss2_url') ?>">
The next block of URL’s are in the navigation bar, all of which currently have a #. They look like:
<li><a href="#">Home</a></li> <li><a href="#">Archives</a></li> <li><a href="#">SiteMap</a></li> <li><a href="#">Contact</a></li>
And you change them to:
<li><a href="<?php bloginfo('url'); ?>" title="<?php bloginfo('name') ?>">Home</a></li>
<li><a href="<?php bloginfo('url'); ?>/archives/" title="View the Archives">Archives</a></li>
<li><a href="<?php bloginfo('url'); ?>/sitemap/" title="View the SiteMap">SiteMap</a></li>
<li><a href="<?php bloginfo('url'); ?>/contact/" title="Send me an email">Contact</a></li>
The function bloginfo('url'); prints the url of the blog. The <?php bloginfo('name') ?> prints the name of the blog. The contents of title are shown on screen when ever you roll the mouse over the graphic and is needed for usability purposes.
The same can be done for the blog title image on line 24:
<div id="title"><a href="#">
Is changed to:
<div id="title"><a href="<?php bloginfo('url'); ?>" title="<?php bloginfo('name') ?>">
This completes the head section.
The Side Bar and Footer
The Footer area is similar to the Sidebar in this theme because they can both hold widgets and/or plugins, so it makes sense to do both at once. There are five “sidebars”:
- Upper Sidebar
- Lower Sidebar
- Left Footer
- Middle Footer
- Right Footer
Each sidebar needs to be setup in the above order. Taking the Upper Sidebar as an example, the code would look like:
<div class="sidebar" id="sbtop">
<ul>
<?php if (!function_exists(’dynamic_sidebar’) || !dynamic_sidebar(1) ) :
<li><p class="sbheader">One</p>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
</li>
<li><p class="sbheader">Two</p>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
</li>
<?php endif;
</ul>
</div>
The additional lines are in red. The two red lines are added to all five "Sidebars", the only difference is the number in the dynamic_sidebar(x), x will be the number given as in the above list.
This is only half the story, the sidebars need to be registered with Wordpress. To do this you create a new file, enter the following code and then save it as functions.php:
<?php register_sidebars(5); ?>
The next step is to modify the style sheet for the widgets. Open the file style.css then down at the bottom in the Footer section find .fmodule .ftitle { and change the line to:
.fmodule .ftitle, .fmodule .widgettitle {
And add this at the bottom of style.css:
.fmodule ul ul li a, .fmodule ul ul li a:visited {
text-decoration: none;
color: #000;
}
.fmodule ul ul li a:hover {
text-decoration: underline;
}
These just change any links to non-underlined black links that appear underlined when the mouse is over them. We need to do a similar thing to the sidebar styles. Find the line #rsidebar p.sbheader { (line 139) and change it to:
#rsidebar p.sbheader, #rsidebar .widgettitle {
Then after line 145 (font-weight: bold;) insert:
font-size: .9em;
Then just before /* FOOTER */ add:
#rsidebar .sidebar ul li li a, #rsidebar .sidebar ul li li a:visited {
display: block;
text-decoration: none;
color: #000;
}
#rsidebar .sidebar ul ul li a:hover {
background: #e0e0e0;
}
Now, save all files, then refresh the browser - there should be no change in appearance.
Go to the Wordpress Admin Panel then click on the Presentation tab and then again on Widgets. You should see five sidebar blocks. The blocks have the same numbering that we gave them earlier, 1 and 2 are the sidebar and 3,4 and 5 are the footer.
Below the blocks are the widgets, you can drag them to whichever sidebar you want. After you have finished dragging click on the Save Changes button. Go back to display the theme and refresh the browser to see the result. Note that some widgets, like the calendar, do not have a title.
The Content Section
For some this might be the most difficult section to understand as it contains the loop that prints out the posts, so I will explain as much as possible what is going on and why.
The first step is to delete the dummy posts, lines 49 to 69.
This is either an empty blog or it has posts, in each case we will do something different, so first of all add this code that decides which path to take:
<?php if (have_posts()) : ?> <?php else : ?> <?php endif; ?>
No Posts
Let’s do the easy one first, no posts. What do you want displayed if there are no posts? A simple text message stating the obvious and maybe a search box is usually enough. The code for this goes in between the else and endif like this:
<?php else : ?>
<h2>Not Found</h2>
<p>Sorry, but you are looking for something that isn’t here.</p>
<?php include (TEMPLATEPATH . "/searchform.php"); ?>
<?php endif; ?>
If you already have some posts you will never see it’s output, so for testing and styling purposes you could copy the 3 lines in between the if and else lines and then delete them when you are finished testing and styling.
The last line needs some explaining! The include function will take the code from another file and insert it where ever the include function is. Here we have a file called searchform.php that has all the code needed for a search form.
The code for searchform.php is:
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>/">
<div><input type="text" value="<?php the_search_query(); ?>" name="s" id="s" />
<input type="submit" id="searchsubmit" value="Search" />
</div>
</form>
This is a standard file, you can type it in if you want but it is easier to just copy the file from the default theme.
We Have Posts
In between the if and else lines we decide if there is a post and if so what to do with it. For this you use a loop that says “While there is a post, I’m gonna display it!”. The code for this is:
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<?php endwhile; ?>
<?php else : ?>
Inside that while loop you print the post’s title, the postmetadata and the actual post. First the title:
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<h2 class="entry-title"><a href="<?php the_permalink() ?>" rel="bookmark"
title="Permanent Link to <?php the_title_attribute(); ?>"><?php
the_title(); ?></a></h2>
<?php endwhile; ?>
<?php else : ?>
That’s a lot of code for one line, but basically it’s header title (h2) with a link (a) to the post’s location.
If you remember (or not
), after the title there was a post div that contained the postmetadata and the actual post, so let’s put the outline of it in:
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<h2 class="entry-title"><a href="<?php the_permalink() ?>" rel="bookmark"
title="Permanent Link to <?php the_title_attribute(); ?>"><?php
the_title(); ?></a></h2>
<div class="post">
<div class="postmetadata">By: Admin | Date: 25/01/08 | Category: General</div>
<div class="postmetadata">
TAGS: this, that, and the other<br />
Comments: 3
</div>
</div>
<?php endwhile; ?>
<?php else : ?>
Now we can add the actual code to display the post itself:
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<h2 class="entry-title"><a href="<?php the_permalink() ?>" rel="bookmark"
title="Permanent Link to <?php the_title_attribute(); ?>"><?php
the_title(); ?></a></h2>
<div class="post">
<div class="postmetadata">By: Admin | Date: 25/01/08 | Category: General</div>
<div class="entry">
<?php the_content(’Read the rest of this entry »’); ?>
</div>
<div class="postmetadata">
TAGS: this, that, and the other<br />
Comments: 3
</div>
</div>
<?php endwhile; ?>
<?php else : ?>
Save and refresh the browser. If you have any posts, you will see them, otherwise you will see the Sorry message and search box.
Now we shall deal with the first postmetadata:
<div class="postmetadata">By: Admin | Date: 25/01/08 | Category: General</div>
Adding the PHP functions changes it to:
<div class="postmetadata">By: <?php the_author() ?> | Date: <?php the_time('F jS, Y')
?> | Category: <?php the_category(', ') ?></div>
the_author() grabs the author’s name. the_time() grabs the post’s date of creation. The letters inside the brackets determine how the date is displayed, more info on these letters can be found in the PHP Manual. the_category() displays the category the post is in. If it’s in more than one (not good for SEO!) they are separated by a comma.
Next is the bottom postmetadata, change:
<div class="postmetadata">TAGS: this, that, and the other<br /> Comments: 3</div>
To:
<div class="postmetadata">
<?php the_tags('Tags: ', ', ', '<br />'); ?>
<?php comments_popup_link('No Comments »', '1 Comment »', '% Comments »'); ?>
</div>
the_tags() will print Tags: followed by the tags separated by a comma and at the end is a line break. If there are no tags, nothing will be printed. If you still want to see Tag: then change that line to:
Tags:<?php the_tags(' ', ', ', ''); ?><br />
The next line in the postmetadata div prints out the number of comments. It is also a link to the comment area of the post. The tags and the comment count are displayed as links, so at the moment they are the default blue and underlined, let’s change that. In style.css find the .postmetadata style, around line 118, and add the following after it:
.postmetadata a, .postmetadata a:visited {
color: #666;
text-decoration: none;
}
.postmetadata a:hover {
color: #000;
text-decoration: underline;
}
This changes the links to dark gray that turn black and underlined when the mouse is over them. We can do the same to the links in the post itself by adding similar code after the last addition:
.entry a, .entry a:visited {
color: #a33;
text-decoration: none;
}
.entry a:hover {
color: #000;
text-decoration: underline;
}
This time I have made the links a brownish color so that they stand out from the rest of the text in the post.
Post Navigation
On the index page you can only have so many posts, especially if they are long posts, so Wordpress breaks up the list into multiple pages. The navigation for this is either at the top or bottom of the page, sometimes both. My preference is at the bottom because I do not want to scroll back to the top just to go to the next page.
The code for this is put between the endwhile (around line 61) and the else:
<?php endwhile; ?>
<div class="navigation">
<div class="alignleft"><?php next_posts_link('« Older Entries') ?></div>
<div class="alignright"><?php previous_posts_link('Newer Entries »') ?></div>
</div>
<?php else : ?>
As you can see there are three style classes there that need defining. In the style.css just before /* SIDEBAR */ add:
.navigation {
background: #ccc;
padding: 5px;
height: 1em;
font-size: .9em;
margin-bottom: 1em;
border: 1px solid #aaa;
}
.navigation a, .navigation a:visited {
color: #000;
text-decoration: none;
}
.alignleft {
float: left;
width: 45%;
}
.alignright {
float: right;
width: 45%;
text-align: right;
}
Wrap Up
The page is more or less finished now. Don’t forget to validate the code. To validate the xhtml use the Web Developer tool bar as usual. If you are using WOS, I found that I could not validate the css.

There are still a number of features to add, such as comments - both reading and making. These features will be added in future posts. You can download all the newly modified files, just right-click the image and download. It’s a zip file that contains the complete theme up to this point.
This post has been submitted to the Home Based Business Group Writing Project.
Next time in the how to create a Wordpress theme series will be a little easier
We shall split the index.php into the separate files header.php, index.php, sidebar.php and footer.php. This will be a major step in being able to create a proper theme.





Morning Chaps,
Just wanted to say how wonderful it is to get these really well thought out tutorials. I have zoomed you and left a longer comment on there.
BUt it is greatly apprceiated.
Just a thought, I really think you could also benefit from a DIGG button as well. It’ a no brainer for people to use if it’s there in front of them. For people like me using Safari, there are no DIGG plugins or extentions to automatic selecting stories to DIGG. Having a button would guarantee you that ‘lazy’ people will DIGG you. Unless ofcourse you don’t want to get DIGG’ed, but I am going through a DIGGING phase at the moment,.
Same could be said of STUMBLE, but Im sure you know all this and you have made these decisions already.
I mention it because your articles in my opinion are worth spreading about and the easier you can make it for us the better.
Also, are you able to post about ‘NoFollow’, how one achieves removing the code and the benefits of doing so. Think this would be a good post.
Graham
“On: Web & Blog Ramblings from the Gutter”
I realise you have the Social Networking links at the bottom, but they tend to not be so visible and so ‘in your face’ and I think for things like being DIGG’ed, like you have with ZOOM, you need to make it more visible.
Just my thoughts
Graham
Wow, Colin, what a terrific tutorial! If I ever happen doing it all on my own I’ll certainly check back to familiarize myself with PHP. Therefore, bookmarked.
Very thorough… like it.
~Marcus
@Graham: Many thx for the Stumble and your kind words
There is no team here, it’s just me writing these posts. This one took longer than expected to produce as I had to do the conversion myself first to make sure it worked. Then do it again and write the post as I do it.
Regarding the social media - I’m still undecided about Digg, from what I’ve read unless your part of clique or write on specific subjects you haven’t a chance because of the ‘bury’ groups.
As for Stumble, I am working on a new plugin that I think would help Stumblers. Zoom was one of the first SG’s I joined that had a widget. After that I didn’t realy want to clutter up the area below the post with to many buttons. I may swap out the Zoom for a Stumble widget… I don’t know… I’m even thinking of removing the current Social plugin as it seems a bit insignificant to me.
I have already posted about dofollow, it’s at Follow You - Follow Me. I wrote it back in Nov. when this site was totally unknown
@Marcus: Thank you, it’s part of a series I’m writing, be sure to subscribe so that you don’t miss a part
How To Create A WordPress Theme - Part 3…
This is the third part in the series about how to create a WordPress theme. In the last part I showed how to convert your idea into a regular html page. In this part I show you how to add the WordPress functions that are needed to make it compatible wi…
Good stuff , Colin , exactly what Im looking for in a Group Writing project I have started
@Don: thx guy, if you want to include this post you are welcome to.
Colin it will be included, please if you can include a link in your post that it has been submitted to the project
Don
[…] week’s selection is a little late as the How To Create A WordPress Theme - Part 3 post took a bit longer to complete than expected. Here are six posts about the different facets of […]
[…] How To Create A Wordpress Theme - Part 3, you created a Wordpress compatible index page. In this part you are going to split into it’s […]
[…] How To Create A WordPress Theme - Part 3 - 750 […]
Very nice. Thanks for the great tutorial. Well thought and step by step. Have you thought about doing a video to walk people through. Just a thought.
all the best,
Patrick
@Patrick: Glad you liked it, look out for my upcoming (free) ebook, a compilation and expansion of these posts. I have thought about it, a video is good for something like Photoshop but for what is basically text… You do not want to watch me typing
[…] programmer as they say find this line and add this after or before it. In fact, I did that in the Create A Wordpress Theme series. This tutorial is different, it shows you all the needed code in comments.php so that you […]