Wordpress Tutorial: How to Create a Wordpress Theme

WordPress Consulting: Looking for professional help with your WordPress project? For small to medium sized projects, check out my freelance page For large projects, contact me through Sabramedia.

WordPress Theme DesignNew Book from Packt Publishers: WordPress Theme Design - Note: Packt has put together some excellent titles in the paste and I've been given the privilege of reviewing them in the past. They've published a new book on WordPress Theme Design and I highly recommend you give it a look.

Tutorial Introduction:

Back in 2005, I wrote a little tutorial for Wordpress 1.5 on how to integrate wordpress with an existing website. Since then, with the release of Wordpress 2.x, working with Wordpress has become even easier. This tutorial is an update to my original tutorial and as it appears under a different name, I want to take a moment to clarify who this tutorial is for.

This tutorial is especially for:

1. People interested in learning how to build a Wordpress theme from scratch or, more specifically, for those interested in taking an existing design and converting it into a beautifully working Wordpress theme.

2. People interested in integrating Wordpress with their existing website. As touched on lightly in my first tutorial, the best way to go about integration, in my experience, is to take your existing website and build a Wordpress theme out of it, then apply that theme to your Wordpress blog and voila, if all has gone well you have a perfect integration. It can require some handiness with CSS, but the principles covered in this tutorial will get you well on your way.

Extra Note on Wordpress Integration:

As questions on integration are the ones I receive most often, I'll take a few more moments to make sure your options are clear. In my experience, there are two ways to integrate Wordpress with an existing website:

Alrighty, let's get started!

Step One: Preparing Your Work Area

Prior to diving into the Wordpress code, we have a few things to make sure we have all straightened out and ready to go. For this tutorial, so as not to pick on anyone else, I'll be using my own blog as an example.

Here's what we need:

  1. A Design - While some folks undoubtedly code their designs directly into a Wordpress theme, we're going to make things a bit simpler and start with a design coded in beautiful HTML and CSS. For your first couple of integrations (or your first and last), I recommend starting with your design already coded. It doesn't have to have all the Wordpress features added in (as you'll see in my example). The most important thing is to have the layout setup and ready to go. While you can do a design in tables, I highly recommend using CSS. For this particular example, we'll be starting with a finished design, coded in CSS and XHTML.
  2. A Wordpress Installation - Be sure you have the lastest version of Wordpress installed and we're ready to go. Most hosting providers provide automatic installations of WordPress. Need help choosing a hosting provider? Take a look at WebHostGear.com or, try blog hosting directly with NetworkSolutions.com.

Here's what I recommend in addition:

  1. Experience with CSS - While not required, having a basic knowledge of CSS will go a long ways in making those extra changes and customizations that come to mind as you assemble your theme. For the sake of this tutorial, I'll make no assumptions about your knowledge of CSS, but will encourage you to have a knowledge nonetheless ;).
  2. A Sense of Humor or Patience or Both - Occasionally when dealing with Wordpress and CSS, things don't go quite as expected. For those of you familiar with CSS and/or PHP, you know that it can be the tiniest little bug that can make everything seem to go crazy. When the bugs pop up, get out the fly swatter and patiently take care of it or, if you're unable to squash it, call in the exterminators.

Alrighty, now that we have that covered, let's reveal our test subject. Click the image to load the HTML.

JonathanWold.com Blog preview

For the sake of this tutorial, I've left the design "incomplete". The layout is finished up, the colors have been selected and a lot of the options have been decided on, but where we might normally take a bit of extra time to put in examples of the Wordpress elements, I've left them intentionally blank. As we continue through the tutorial, we'll add them in and have a chance to learn a bit about "template tags" ;).

[Note: Those familiar with CSS can skip this paragraph] - If you take a look at the source code, you'll notice that other than the content, there's not a whole lot of code to look at. You can especially notice this if you hunt down an old site that uses <table>'s and compare the code. This is because the layout has been built in CSS (Cascading Style Sheets). That means that instead of using "tables" to lay out where everything goes, the design has been separated from the content through the use of an external stylesheet. While I've done a number of integrations for clients with table based websites, being able to work with CSS makes things a whole lot easier.

Alrighty, now that we've had a chance to look at our test subject, let's take a bold step forward and begin building our theme! First though, stand up, stretch, get a glass of water and then sit back down. Too many hours at the computer without a break and we'll end up looking like Quasimodo.

Step Two: Preparing Your Theme Creation Playground

Now, while there are some out there who know all the Wordpress template tags off the top of their head (I'm not quite there yet), for the rest of us it helps to have a place to start. In a best case scenario, you just pull out your already prepared Wordpress theme, loaded with all the features you like to use, and simply replace the existing style sheet with your own. But for the sake of this tutorial, we're going to work with the good old default Wordpress theme (Kubrick) prepared by our good friends at BinaryBonsai.com.

What we're going to do is take the default Wordpress theme, clean it up, and then use it as a starting point for making our own.

To get started, copy the "default" theme from your Wordpress installation (located in wp-content/themes/) and paste it in a new folder along with a copy of your design. You do these steps anyway you like, but I find it helps to keep things organized. Here's how my folder looks:

Desktop Theme Folder

As you may have guessed, to avoid any confusion when it comes time to upload, I've renamed the "default" theme to "blog_theme".

The pretty flowers, by the way, are from a series of photos I took during a 2 month volunteer stay in the Dominican Republic early in 2007. Not typically a "flowers-on-my-desktop" kind of developer, I had to make an exception for these ;).

 

 

Step Three: Diving Into The Code - Creating the Header

Now that we've got our design and a copy of Wordpress ready to go, it's time to open up the "default" theme, clean things out a bit, and start making our new theme. Let's get started:

  1. First, we open up header.php. You should see something that looks very much like this:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

    <head profile="http://gmpg.org/xfn/11">
    <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />

    <title><?php bloginfo('name'); ?> <?php if ( is_single() ) { ?> &raquo; Blog Archive <?php } ?> <?php wp_title(); ?></title>

    <meta name="generator" content="WordPress <?php bloginfo('version'); ?>" /> <!-- leave this for stats -->

    <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
    <link rel="alternate" type="application/rss+xml" title="<?php bloginfo('name'); ?> RSS Feed" href="<?php bloginfo('rss2_url'); ?>" />
    <link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

    <style type="text/css" media="screen">

    <?php
    // Checks to see whether it needs a sidebar or not
    if ( !$withcomments && !is_single() ) {
    ?>
    #page { background: url("<?php bloginfo('stylesheet_directory'); ?>/images/kubrickbg.jpg") repeat-y top; border: none; }
    <?php } else { // No sidebar ?>
    #page { background: url("<?php bloginfo('stylesheet_directory'); ?>/images/kubrickbgwide.jpg") repeat-y top; border: none; }
    <?php } ?>

    </style>

    <?php wp_head(); ?>
    </head>
    <body>
    <div id="page">

    <div id="header">
    <div id="headerimg">
    <h1><a href="<?php echo get_option('home'); ?>/"><?php bloginfo('name'); ?></a></h1>
    <div class="description"><?php bloginfo('description'); ?></div>
    </div>
    </div>
    <hr />

  2. Remove the sections of code marked above in red. Excellent! Save your work.
  3. Now, open up the HTML file that contains your layout. Here's the full mark up for my layout:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html><head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Life of an Internet Entrepreneur - Jonathan Wold</title>
    <link href="style.css" rel="stylesheet" type="text/css" /></head>
    <body>

    <div id="mainContainer">

    <div id="header"></div>


    <div id="notice"><p>Important Notice Goes Here</p></div>

    <div id="contentContainer" class="withSidebar">
    <div id="content">

    <div id="contentHeader"><h1>Content Title Goes Here</h1></div>

    <p>Lorem ipsum dolor sit amet. Con minimim venami quis nostrud laboris nisi ut aliquip ex ea com dolor in reprehenderit in voluptate nonumi. Mimimum veniami ex ea con dolor nisi ut aliquip. Consequat Duis autem vel eum iruire dolor in endrerit, voluptate velit est. Sit amet, consectetuer adipiscing elit, sed diam nonummi. Euismod tincidunt ut laroeet dolore magna aliquam erat voluptat.</p>
    <p>Ut wisi enin ad minim. Quis nostrud ad nostris pro amat. Sed aliquo ut nisi alter ego qid propter anno et cetera. Ullam venit cum permissio, alter ego cum frater et patris et mater inter familias. Vel illum dolore eu feugiat nulla facilitis ad vero eros et accususam et lustro odio dignissim qui blandit praeset lupatum auge duis aplore. Mimimum veniami ex ea con dolor nisi ut aliquip. Consequat Duis autem vel eum iruire dolor in endrerit, voluptate velit est. Sit amet, consectetuer adipiscing elit, sed diam nonummi.</p>

    <span class="readMore">Continue Reading</span>

    <div id="contentFooter">
    <p>Published May 2, 2007 - Comments? None yet </p>
    </div>

    </div> <!-- Content Ends -->
    </div> <!-- Content Container Ends -->

    <div class="rightColumnContainer">
    <div class="rightColumn">

    <h2>The Author</h2>
    <p class="small">Jonathan Wold is a 20 year old Internet Entrepreneur who believes that faith and works are inseparable. Here you’ll find examples of faith, web design, niche marketing, CSS, Wordpress, and more.</p>

    <h2>Categories</h2>
    <ul>
    <li>Niche Marketing (15)</li>
    <li>Faith I Live By (12)</li>
    <li>Web Design (5)</li>
    <li>Life Updates (9)</li>
    <li>Wordpress (15)</li>
    </ul>

    <h2>Blog Pages</h2>
    <ul>
    <li>Excellent Blogs</li>
    <li>Excellent Websites</li>
    <li>Excellent Books</li>
    <li>Active Projects</li>
    </ul>

    </div> <!-- First "box" of content ends here, second box begin below -->

    <div class="rightColumn">

    <h2>Sponsors</h2>
    <p>Sponsor This Site</p>

    </div> <!-- 2nd box of content ends here -->

    </div> <!-- Right Column Container Ends -->

    <div id="clear"></div>

    <div id="footer">
    <p>You're welcome to share what you find here with whomever you'd like in whatever way you'd like to. If you have questions, comments, or suggestions, contact me :).</p>
    <p>Virtual Empire (What is this?): <a href="#">Links to Various Sites </a></p>
    </div>

    </div> <!-- Main Container Ends -->

    </body>
    </html>

    Note: For the sake of easy reference in the above layout, I've color coded my theme to match the appropriate Wordpress theme files. Blue is for header.php, green is for index.php (as well as single.php, page.php, archive.php, search.php, etc), orange is for sidebar.php, and purple is for footer.php. - For the examples in the next few tutorial stepsl, I'll just stick with blue.

  4. Now, take the "header" section from your layout and place it, as appropriate, into the Wordpress header template, replacing the relevant pieces of existing code with your own. Keep in mind that this header.php file represents what will be at the top of every page of your new Wordpress theme (unless you specify otherwise). Here's my finished header template with my changes marked in blue:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

    <head profile="http://gmpg.org/xfn/11">
    <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />

    <title> <?php simple_title('-'); ?> <?php bloginfo('name'); ?> </title>

    <meta name="generator" content="WordPress <?php bloginfo('version'); ?>" /> <!-- leave this for stats -->

    <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
    <link rel="alternate" type="application/rss+xml" title="<?php bloginfo('name'); ?> RSS Feed" href="<?php bloginfo('rss2_url'); ?>" />
    <link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

    <?php wp_head(); ?>
    </head>
    <body>

    <div id="mainContainer">

    <div id="header"></div>

    You'll notice that I replaced the default way of displaying the page title. I wanted a title that read like "Page Name - Website Name", rather than the Wordpress default. "simple_title" is the name of my own rendering of the excellent plugin developed by Aaron Schaefer of ElasticDog.com.

Step Four: Customizing the Index

Alrighty! We've finished up our header template and now it's time to work on the index.

  1. Open up the "default" template (index.php) and take a look. You should see something like this:

    <?php get_header(); ?>

    <div id="content" class="narrowcolumn">

    <?php if (have_posts()) : ?>

    <?php while (have_posts()) : the_post(); ?>

    <div class="post" id="post-<?php the_ID(); ?>">
    <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h2>
    <small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>

    <div class="entry">
    <?php the_content('Read the rest of this entry &raquo;'); ?>
    </div>

    <p class="postmetadata">Posted in <?php the_category(', ') ?> | <?php edit_post_link('Edit', '', ' | '); ?> <?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?></p>
    </div>

    <?php endwhile; ?>

    <div class="navigation">
    <div class="alignleft"><?php next_posts_link('&laquo; Previous Entries') ?></div>
    <div class="alignright"><?php previous_posts_link('Next Entries &raquo;') ?></div>
    </div>

    <?php else : ?>

    <h2 class="center">Not Found</h2>
    <p class="center">Sorry, but you are looking for something that isn't here.</p>
    <?php include (TEMPLATEPATH . "/searchform.php"); ?>

    <?php endif; ?>

    </div>

    <?php get_sidebar(); ?>

    <?php get_footer(); ?>

    (Skip if you have a basic understanding of PHP)

    Brief Explanation: Let's take a moment to look at how this template works. At the top, we have <?php get_header(); ?>. What does this do? This tells Wordpress to look for the header.php file and "include" it when it generates the default index page for your new Wordpress theme.

    Then, the Wordpress "Loop" begins with <?php if (have_posts()) : ?>. Inside this piece of code, which ends with <?php endif; ?>, Wordpress "includes" the content published from within the Wordpress Admin. For a simple blog theme, this would include your latest posts. Within the Wordpress Loop we are able to use HTML as well as Wordpress tags to decide what content to include and how we want it to be displayed.

    For example, let's quickly look at the following piece of code:

    <small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>

    The <?php ?> elements draw information from Wordpress and delivers it to you to format as you'd like. <?php the_author() ?>, when placed within The Loop, prints the name of the author of the current post, as defined within the Wordpress Admin. Notice that it has HTML comment tags around it. This means that even though it's there in the source code, the "default" template author has decided not to display it.

    Let's practice a quick rearrangement:

    <span class="author">Cheerfully writen on <?php the_time('M d, Y') ?> by <?php the_author() ?></span>

    The template tags will be dynamically replaced with the information from Wordpress and the output would look something like this:

    Cheerfully written on May 2, 2007 by Jonathan

  2. Alright, moving forward! : ) - Take the existing index.php file and modify it, adding the elements from your own design and replacing your static elements with the Wordpress template tags as appropriate.

    For example, take the following piece of code: <div id="contentHeader"><h1>Content Title Goes Here</h1></div> - In order to have Wordpress replace "Content Title Goes Here" with the title of our Wordpress post, all we'd have to do is change that piece of code to look like this:

    <div id="contentHeader"><h1><?php the_title(); ?></h1></div>

    Pretty nifty eh? In my example below, we've taken it a step further and made the title a link, using Wordpress to dynamically grab the post URL, <?php the_permalink() ?>, and place it within our <a> tag. Take a look at the complete example below with changes marked in blue.

    <?php get_header(); ?>

    <div id="notice"><p>Important Notice Goes Here</p></div>

    <div id="contentContainer" class="withSidebar">
    <div id="content">

    <?php if (have_posts()) : ?>

    <?php while (have_posts()) : the_post(); ?>

    <div id="contentHeader"><h1><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h1></div>

    <?php the_content('Read More'); ?>

    <span class="readMore">Continue Reading</span>

    <div id="contentFooter"><p>Published <?php the_time('M d, Y') ?> - <?php comments_popup_link('Comments? None yet', '1 Comment so far', '% Comments and counting'); ?> </p></div>

    <?php endwhile; ?>

    <?php else : ?>

    <h2 class="center">Not Found</h2>
    <p class="center">Sorry, but you are looking for something that isn't here.</p>
    <?php include (TEMPLATEPATH . "/searchform.php"); ?>

    <?php endif; ?>

    </div> <!-- Content Ends -->
    </div> <!-- Content Container Ends -->

    <?php get_sidebar(); ?>

    <?php get_footer(); ?>

Step Five: Customizing the Sidebar

Now that we have the header and the main index template in place, it's time to tackle the sidebar. For those of you working on a theme without a sidebar feel free to skip this section. But for the sake of some of the more advanced things we'll be covering, I'd recommend looking it over just to be sure you didn't miss anything.

  1. Let's begin once again by taking a look at the "default" source code:

    <div id="sidebar">
    <ul>

    <li>
    <?php include (TEMPLATEPATH . '/searchform.php'); ?>
    </li>

    <!-- Author information is disabled per default. Uncomment and fill in your details if you want to use it.
    <li><h2>Author</h2>
    <p>A little something about you, the author. Nothing lengthy, just an overview.</p>
    </li>
    -->

    <li>
    <?php /* If this is a 404 page */ if (is_404()) { ?>
    <?php /* If this is a category archive */ } elseif (is_category()) { ?>
    <p>You are currently browsing the archives for the <?php single_cat_title(''); ?> category.</p>

    <?php /* If this is a yearly archive */ } elseif (is_day()) { ?>
    <p>You are currently browsing the <a href="<?php bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for the day <?php the_time('l, F jS, Y'); ?>.</p>

    <?php /* If this is a monthly archive */ } elseif (is_month()) { ?>
    <p>You are currently browsing the <a href="<?php bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for <?php the_time('F, Y'); ?>.</p>

    <?php /* If this is a yearly archive */ } elseif (is_year()) { ?>
    <p>You are currently browsing the <a href="<?php bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for the year <?php the_time('Y'); ?>.</p>

    <?php /* If this is a monthly archive */ } elseif (is_search()) { ?>
    <p>You have searched the <a href="<?php echo bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for <strong>'<?php the_search_query(); ?>'</strong>. If you are unable to find anything in these search results, you can try one of these links.</p>

    <?php /* If this is a monthly archive */ } elseif (isset($_GET['paged']) && !empty($_GET['paged'])) { ?>
    <p>You are currently browsing the <a href="<?php echo bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives.</p>

    <?php } ?>
    </li>

    <?php wp_list_pages('title_li=<h2>Pages</h2>' ); ?>

    <li><h2>Archives</h2>
    <ul>
    <?php wp_get_archives('type=monthly'); ?>
    </ul>
    </li>

    <?php wp_list_categories('show_count=1&title_li=<h2>Categories</h2>'); ?>

    <?php /* If this is the frontpage */ if ( is_home() || is_page() ) { ?>
    <?php wp_list_bookmarks(); ?>

    <li><h2>Meta</h2>
    <ul>
    <?php wp_register(); ?>
    <li><?php wp_loginout(); ?></li>
    <li><a href="http://validator.w3.org/check/referer" title="This page validates as XHTML 1.0 Transitional">Valid <abbr title="eXtensible HyperText Markup Language">XHTML</abbr></a></li>
    <li><a href="http://gmpg.org/xfn/"><abbr title="XHTML Friends Network">XFN</abbr></a></li>
    <li><a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art semantic personal publishing platform.">WordPress</a></li>
    <?php wp_meta(); ?>
    </ul>
    </li>
    <?php } ?>

    </ul>
    </div>

  2. Whew! As you can see with all the items marked in red to be changed , we've got quite a bit of work to do! The default Wordpress theme uses an unordered list to "contain" the menu items, each element in the sidebar being contained within a list item (<li>) and each of those list items having its own sublists as appropriate. For the sake of my design and for the sake of giving an example that the majority would find relevant, we're going to bust the sidebar out of its unordered list and do some creative rearrangement.

    First, the final code, then we'll disect it : ).

    <div class="rightColumnContainer">
    <div class="rightColumn">

    <h2>The Author</h2>
    <p class="small">Jonathan Wold is a 20 year old Internet Entrepreneur who believes that faith and works are inseparable. Here you'll find examples of faith, web design, niche marketing, CSS, Wordpress, and more.</p>


    <?php /* If this is a 404 page */ if (is_404()) { ?>
    <?php /* If this is a category archive */ } elseif (is_category()) { ?>
    <p>You are currently browsing the archives for the <?php single_cat_title(''); ?> category.</p>

    <?php /* If this is a yearly archive */ } elseif (is_day()) { ?>
    <p>You are currently browsing the <a href="<?php bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for the day <?php the_time('l, F jS, Y'); ?>.</p>

    <?php /* If this is a monthly archive */ } elseif (is_month()) { ?>
    <p>You are currently browsing the <a href="<?php bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for <?php the_time('F, Y'); ?>.</p>

    <?php /* If this is a yearly archive */ } elseif (is_year()) { ?>
    <p>You are currently browsing the <a href="<?php bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for the year <?php the_time('Y'); ?>.</p>

    <?php /* If this is a monthly archive */ } elseif (is_search()) { ?>
    <p>You have searched the <a href="<?php echo bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives
    for <strong>'<?php the_search_query(); ?>'</strong>. If you are unable to find anything in these search results, you can try one of these links.</p>

    <?php /* If this is a monthly archive */ } elseif (isset($_GET['paged']) && !empty($_GET['paged'])) { ?>
    <p>You are currently browsing the <a href="<?php echo bloginfo('home'); ?>/"><?php echo bloginfo('name'); ?></a> weblog archives.</p>

    <?php } ?>

    <h2>Pages of Interest</h2>
    <ul>
    <?php wp_list_pages('title_li='); ?> <!-- This fetches a list of pages with an <li> tag without a headline -->
    </ul>

    <h2>Post Categories</h2>
    <ul>
    <?php wp_list_categories('show_count=1&title_li='); ?> <!-- This does the same -->
    </ul>

    <h2>Post Archives</h2>
    <ul>
    <?php wp_get_archives('type=monthly'); ?>
    </ul>

    <h2>Looking for more?</h2>
    <?php include (TEMPLATEPATH . '/searchform.php'); ?>


    </div> <!-- 1st "Box" ends here - 2nd Column Box Begins Below -->

    <div class="rightColumn base">

    <h2>Sponsors</h2>
    <p><a href="http://jonathanwold.com/sponsors">Sponsor This Site</a></p>

    </div> <!-- 2nd Column Box Ends Here -->
    </div> <!-- Right Column Container Ends -->

    Aside from the dynamic messages (which I'll customize later), you can see that everything has been modified from the original. While there's a lot that can be pointed out and explained here (and I'll be happy to upon request), I'm going to highlight the use of the Wordpress template tags and leave the rest for you guys to play around with.

    Let's take a look at the "Pages" template tag (wp_list_pages). This handy little tag creates a list of all the "pages" you've made in Wordpress and displays them. Within the tag you're able to pass parameters that tell Wordpress how it should be formatted, what to display, etc. To learn more, I highly recommend reading through the list of Template Tags in the Wordpress Codex.

    Alright, let's look at an example. The "default" theme uses the following to display a list of pages:

    <?php wp_list_pages('title_li=<h2>Pages</h2>' ); ?>

    This takes the list of pages from Wordpress and then adds a handy little <h2> tag right on top of it. This would be excellent for me to use, except that Wordpress also puts the "pages" element inside of a list item so that the code would look like this:

    <li class="pagenav"><h2>Pages of Interest</h2><ul><li class="page_item"><a href="http://woldboys.com/testing/?page_id=2" title="About">About</a></li>
    </ul></li>

    With the markup I've chosen, this would render the XHTML invalid and as I don't want that, the simple work around is to take the responsibility of adding a header away from Wordpress. To do so, I simply pass the "title_li" parameter as null, like so:

    <?php wp_list_pages('title_li='); ?>

    And there you have it! : ) - Reference the list of Template Tags in the Codex to learn more about what parameters you can use to customize each of the Wordpress template tags.

Step Six: Finishing up with the Footer

Alrighty! We're almost there! Let's get started on the footer.

  1. First, let's take a look at our "default" footer:

    <hr />
    <div id="footer">
    <!-- If you'd like to support WordPress, having the "powered by" link someone on your blog is the best way, it's our only promotion or advertising. -->
    <p>
    <?php bloginfo('name'); ?> is proudly powered by
    <a href="http://wordpress.org/">WordPress</a>
    <br /><a href="<?php bloginfo('rss2_url'); ?>">Entries (RSS)</a>
    and <a href="<?php bloginfo('comments_rss2_url'); ?>">Comments (RSS)</a>.
    <!-- <?php echo get_num_queries(); ?> queries. <?php timer_stop(1); ?> seconds. -->
    </p>
    </div>
    </div>

    <!-- Gorgeous design by Michael Heilemann - http://binarybonsai.com/kubrick/ -->
    <?php /* "Just what do you think you're doing Dave?" */ ?>

    <?php wp_footer(); ?>
    </body>
    </html>

  2. Next, let's take a look at our modifications:

    <br id="clear" />

    <div id="footer">
    <p>You're welcome to share what you find here with whomever you'd like in whatever way you'd like to. If you have questions, comments, or suggestions, <a href="http://jonathanwold.com/contact">contact me</a> :).</p>
    </div>

    </div> <!-- Main Container Ends -->

    <?php wp_footer(); ?>
    </body>
    </html>

    Note: Even if you didn't notice, I'd like to be sure to point out that I've removed the Wordpress link from my footer. While it won't be at the bottom of this particular theme, unintended for public distribution, I want to be clear that I am in no way withdrawing my support of Wordpress : ). There will be a link in my list of recommended sites and I will continue to show my support through open source theme and plugin releases, tutorials, and my continuous recommendations to those I come in contact with.

    In working on your theme, if you don't have another way of showing support for the excellent work the Wordpress team has done, I recommend leaving the link in place : ).

Step Seven: Off on your own - Additional Template Pages

Now that we've covered the basics, it's time to step into new territory and do some experimenting of your own. For this particular theme, I will continue the customization by modifying the following template files:

There's a whole lot more work that I'll be doing on this particular theme, but for the sake of keeping things basic, I'll talk about that in future tutorials. I'll be creating templates for individual posts, etc, and adding more dynamic elements within the template. For now, though, we'll just keep things basic.

Step Eight: Finalization

The last step is to replace the styles in style.css with your own and to edit the theme information. The header comments "default" CSS sheet read as follows:

/*
Theme Name: WordPress Default
Theme URI: http://wordpress.org/
Description: The default WordPress theme based on the famous <a href="http://binarybonsai.com/kubrick/">Kubrick</a>.
Version: 1.6
Author: Michael Heilemann
Author URI: http://binarybonsai.com/

Kubrick v1.5
http://binarybonsai.com/kubrick/

This theme was designed and built by Michael Heilemann,
whose blog you will find at http://binarybonsai.com/

The CSS, XHTML and design is released under GPL:
http://www.opensource.org/licenses/gpl-license.php

*/

And my simple modification:

/*
Theme Name: Light Blue '07
Theme URI: http://www.wpmastery.com
Description: A simple theme for Jonathan's blog
Version: 1.0
Author: Jonathan Wold
Author URI: http://www.jonathanwold.com

*/

And there you have it : ). Excellent work!

End Notes and Future Tutorials

I really enjoy working with Wordpress. The development team has done an excellent job of putting together a stable piece of software that provides an almost limitless flexability. I've yet to take on a project that Wordpress hasn't been able to handle. Here are a few suggestions for taking your Wordpress theme development and customization even further:

As time and projects permit, I'll be covering some of the above ideas and more in future tutorials. Until then and after, I'd be happy to hear any comments or suggestions you have in regards to this particular tutorial. Once you've finished it up, show me your work! : )

Enjoy your time with Wordpress!

-Jonathan Wold

WordPress Consulting: Looking for professional help with your WordPress project? For small to medium sized projects, check out my freelance page For large projects, contact me through Sabramedia.