Today we’ll be building a minimalist Wordpress theme from a Photoshop mock up. We’ll start from scratch, so we can really understand how themes work within Wordpress, and what a real life workflow looks like. There will even be some custom PHP function code. Yikes! The theme’s files are located here. Once we finish, we’ll move on to part 2, where we build out the rest of the site’s pages, and end up with a complete Wordpress theme.
Step 1 – Analyzing your PSD
First, we’ll take a look at the mockup we’ll be using.You’ll notice it doesn’t look very complicated.
That’s a Good Thing, because building a Wordpress theme from scratch involves a lot of steps. For our first theme, it’s much better to keep things simple, so we can focus on the individual steps. First, we’ll split our mock up into HTML, then we’ll add our CSS and images. Next, we’ll replace the static html code with dynamic Wordpress template code. Finally, we’ll break our code off into individual files, so our header, footer, and functions can be reused by every template we create.
I also like to get an idea for what portions of my mockup will be dynamic here. Greed, Power, and Avarice will be categories, and the rest is outlined below.
Step 2 – Breaking the PSD Down into HTML
We’ll start with the top portion of the PSD. I like to make the html mockup as easy as possible by breaking everything down into div’s.
So, we’ll create a wrapper div, because this layout wants to be centered. Then a header div, just to make things easier to edit later on. Finally, I’ll break the logo, site name, and main image into their own divs, and add an unordered list for the navigation. Also, we’ll create comments where we want dynamic Wordpress code to go later.
<html> <header> <title>zothcorp theme</title> </header> <body> <div id="wrapper"> <div id="header"> <div id="logo"><img src="logo.png" alt="" /></div> <div id="sitename">zothcorp<!-- Wordpress Site Name Code Here --></div> <!-- We use this because we're floating the logo and sitenames --> <hr /> <!-- the line separating the words --> <div id="mainimage"><img src="images/mainimage.jpg" alt="" /><!-- Wordpress Main Image Code Here --></div> <div id="sitenav"> <ul> <li><a href="#">Home</a> <!-- Wordpress Navigation links here --></li> <li><a href="#">About</a></li> <li><a href="#">Family</a></li> <li><a href="#">Team</a></li> <li><a href="#">Propaganda</a></li> <li></li> <!-- This gives us the last background line --></ul> </div> </div> <!-- End Header --> </div></body></html>
Next, we’ll break down the body. It’s looks pretty straightforward, we’ll break down the two different post sizes with two different div classes.
When we create the code this time, we’ll be sure to include the same content we had in our mockup. We’re left with the following code.
<!-- Begin Wordpress Content --> <div id="content"> <div class="firstcol"> <span>Greed</span> <!-- Category Name --> <div class="wideimage"> <img src="images/1.jpg" alt="" /> <!-- Post Picture --> <span> Being A Winner</span> <!-- Post Name --> </div> <div class="introtext"> "There is a dog who knows more than me. His name is..." <!-- Post Excerpt --> </div> </div> <!-- End 1st FirstCol --> <div class="firstcol"> <span>Power</span> <!-- Category Name --> <div class="wideimage"> <img src="images/2.jpg" alt="" /> <!-- Post Picture --> <span> Finding Hidden Meanings</span> <!-- Post Name --> </div> <div class="introtext"> “People always said there was something funny about him, I ...”<!-- Post Excerpt --></div> </div> </div> <!-- End 2nd FirstCol --> <div class="secondcol"> <span>Avarice</span> <!-- Category Name --> <div class="boximage"> <img src="images/3.jpg" alt="" /> <span> Tiny White Dies</span></div> <div class="introtext"> “Nouns, kid. They folow you until rats...”<!-- Smaller Post Excerpt --></div> </div> <!-- End SecondCol --> <!-- End Wordpress Content -->
Finally, we’ll end with our footer. Our footer in the mockup is easy enough. We don’t even need to create a layout. All we need is a #footer wrapper and some filler text from our mockup. Then the final html to close the document up.
<!-- Begin Wordpress Footer --> <div id="footer"> zothcorp is copyright with mega death enforcement by kirk “the gentle lion” kaiser </div> <!-- End Wordpress Footer -->
All our HTML is now cleanly laid out into one nice big HTML file. Next, we’ll export our images and measure distances, so we can get ready to transform our HTML into CSS’ified goodness. Because as is, the theme’s kinda ugly:
Step 3 – Slicing Images and Taking Measurements
Start by looking at the header. We’ll want to keep the logo as a separate file, and I prefer png files. Crop it down, keeping the whitespace around it to a minimum. This will be our first image exported. If you’re working in Photoshop, I like to Crop, followed by a File -> Save for Web and Devices. Then save your logo with the same filename you gave it in your mockup. In my case, it was ‘logo.png’.
Continue on, the next image we’ll export is the main image. In analyzing the layout, I decided this image wouldn’t be managed by Wordpress. Instead, I’ll change it myself manually on the web server. So I crop out the image using the same process as the logo, but write down the width of my image. It sets down the width for everything else below it, at 946px.
Next, we’ll slice the smaller images that make up our latest posts. We’ll cut them out, and take note of both their width and height. In this case, it’s 350px X 175px for the bigger “.firstcol” images, and 220px X 175px for the even smaller “.secondcol” images.
Finally, we measure the distances between our individual body elements. I like to use the Measure Tool in Photoshop to make this go really quickly. Doing so, I find out the distance from the HR tag and the Main Image is 5px. Repeat this for the rest of the main body elements. Because next, we’re going to make that layout have some CSS pizazz!
Step 4 – Adding CSS Magic to Our HTML Framework
Using our previous HTML mockup and our basic measurements, we can begin to fill out the CSS behind our HTML layout. Begin by creating a new CSS file and linking to it from within our previously created HTML layout. Or, make things really easy and just create a new CSS style right after the Title Tag like so:
<title>zothcorp theme</title>
<!-- Begin Inserted Code -->
<style type="text/css">
#wrapper {
width: 946px;
}
#mainimage {
margin-top: 5px;
}
.firstcol {
width: 350px;
height: 175px;
}
.secondcol {
width: 220px;
height: 175px;
}
</style>
<!-- End Inserted Code -->
You’ll see I already added the measurements we took in Step 3. These help structure our document and give us a rough look at how things are shaping up. Next, we can go back into Photoshop and begin changing our colors and fonts in our CSS to match our Photoshop mock ups. Use the Eyedropper Tool to pick up the exactly right color from your mockup.
While I’m creating CSS from a PSD, I like to keep things simple by testing only in Firefox. I find things flow better when focused on getting things working in one browser, and ignore errors in others until finished. A handy Firefox’s addon, Firebug, makes it easy to quickly change CSS and tweak little things while developing.
Converting this design to CSS is pretty straightforward, and the only thing that might give you a bit of trouble is the unordered list. It gave me a bit of trouble, so here’s the code for that, specifically, with some comments:
#sitenav {
width: 100%;
background-color:#333;
margin-top: 11px;
height: 30px;
}
#sitenav ul {
margin: 0; /* Necessary to keep our li's aligned */
padding: 0;
list-style-type: none;
text-align: left;
padding-bottom: 0px;
padding-top: 4px;
padding-left: 4px;
}
#sitenav li {
display: inline;
margin-left: -2px; /* Keeps the first line from showing up on the list */
}
#sitenav a, #sitenav a:visited {
padding: 5px 36px 4px 8px; /* Make a box around links for the mouseover to change the background */
color: white;
text-decoration: none;
font-size: 1.8em;
border-right: 1px solid #fff;
}
#sitenav a:hover {
background-color: #222;
}
After a bit of work, your CSS should give you a layout that looks a lot like your mockup. So much so, in fact that you might not be able to tell a difference between the mockup and the final site:
Step 5 – From Static to Dynamic – Baby Steps
Finally, it’s time to start converting all our work to Wordpress. Begin by creating a new folder. Within it, we’ll create two new files. One named “index.php”, and one name “style.css”. This is the beginning of our new theme. Copy and paste your CSS file created earlier into “style.css”. Do the same with your HTML file, into the “index.php” file.
Every Wordpress Theme must identify itself, and ours is no different. Open your newly created “style.css” file, and add the following at the beginning:
/* Theme Name: zothcorp unloaded Theme URI: http://zothcorp.com Description: zothcorp minimalist theme Version: 1.0 Author: Kirk Kaiser Author URI: http://www.zothcorp.com/ */
This code shows up when we browse to it within Wordpress. If you’re working on a local copy of Wordpress, go ahead and copy this folder to the themes/ directory. Browse to your themes within the Wordpress Admin, and you should see your new theme. Set it as your default.
Hoorah, you should see your theme looking perfect now. Only problem is, it doesn’t do anything. Yet.
Step 6 – From Static to Dynamic – Basic PHP Hooks
Next, we’ll begin to add the dynamic features we decided on earlier. We’ll begin with the head of index.php, where the CSS file is loaded. If you finished the previous step and didn’t see a perfect site, your CSS file might not have loaded correctly. Let’s fix that, and add our basic header hooks. Open up your index.php file, and replace your head with the following:
< ?php
/**
* @package WordPress
* @subpackage zothcorp_theme
*/?>
< !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 wp_title('«', true, 'right'); ?> < ?php bloginfo('name'); ?></title>
<style type="text/css" media="screen">
@import url( < ?php bloginfo('stylesheet_url'); ?> );
</style>
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="<?php bloginfo('rss2_url'); ?>" />
</link><link rel="alternate" type="text/xml" title="RSS .92" href="<?php bloginfo('rss_url'); ?>" />
</link><link rel="alternate" type="application/atom+xml" title="Atom 1.0" href="<?php bloginfo('atom_url'); ?>" />
</link><link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
< ?php wp_get_archives('type=monthly&format=link'); ?>
< ?php //comments_popup_script(); // off by default ?>
< ?php wp_head(); ?>
</link></meta></head></html>
The beginning of this code is mostly default Wordpress stuff you just put in. You’ll notice the only things that really matter to us in the Head are the Title tag, that fetches the Wordpress Blog post name, and the Stylesheet tag, that fetches the stylesheet url.
Every Wordpress head is supposed to include the wp_head(); functon, so plugins can hook within it.
Alright, now to the meat and potatoes, the code that matters. Replace the following code within index.php:
<body>
<div id="wrapper">
<div id="header">
<div id="logo"><img src="/images/logo.png" /></div>
<div id="sitename"><a href="<?php bloginfo('url'); ?>/">< ?php bloginfo('name'); ?></a><!-- Wordpress Site Name Code Here --></div>
<br clear="all" />
<hr />
<div id="mainimage"><img src="/images/mainimage.jpg" /><!-- Wordpress Main Image Code Here --></div>
<div id="sitenav">
<ul>
<li><a href="<?php bloginfo('url'); ?>/">Home</a></li> <!-- Wordpress Home Page -->
< ?php wp_list_pages('title_li='); ?> <!-- Wordpress Pages Here -->
</ul>
</div>
</div>
<div id="content">
<!-- end header --></div></div></body>
You’ll see we don’t change much. The logo stays the same, the site name becomes dynamic. It’s wrapped in a link, and we get the blog link from the <?php bloginfo(’url’); ?> tag. Then we get our blog name from the <?php bloginfo(’name’); ?> tag. Easy enough!
The main image stays the same, and we add a homepage link to the unordered list. Then we call <?php wp_list_pages(’title_li=’); ?>, and it gives us a list of all the pages currently on the site. The ‘title_li=’ part is important, because otherwise Wordpress gives us a list with a title. Try stripping it out to see what I mean.
Save your changes, and our Wordpress site has become just a little bit more dynamic. All we need to add now is the content and the footer. So much closer than at the beginning!
Step 7 – From Static to Dynamic – Entering The Loop
Next, we’re going to fetch Wordpress categories in our main body. The code for this is simple and straightforward. In our index.php file, scroll to the content. Change the following code:
<!-- Begin Wordpress Content -->
<div id="content">
< ?php $my_query = new WP_Query('category_name=greed&showposts=1'); /* Get the Greed Category's Most Recent Post */
while ($my_query->have_posts()) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>
<div class="firstcol">
<span>< ?php the_category(' '); ?></span><!-- Category Name -->
<div class="wideimage">
< ?php dp_attachment_image($post->ID, 'thumbnail', 'alt="' . $post->title . '"'); ?> <!-- Post Picture -->
<span> <a href="<?php echo get_permalink(); ?>">< ?php the_title(); ?></a></span> <!-- Post Name -->
</div>
<div class="introtext">
<a href="<?php echo get_permalink(); ?>">< ?php the_excerpt(); ?></a><!-- Post Excerpt -->
</div>
</div>
< ?php endwhile; ?>
< ?php $my_query = new WP_Query('category_name=power&showposts=1'); /* Get the Power Category's Most Recent Post */
while ($my_query->have_posts()) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>
<div class="firstcol">
<span>< ?php the_category(' '); ?></span><!-- Category Name -->
<div class="wideimage">
< ?php dp_attachment_image($post->ID, 'thumbnail', 'alt="' . $post->title . '"'); ?> <!-- Post Picture -->
<span> <a href="<?php echo get_permalink(); ?>">< ?php the_title(); ?></a></span> <!-- Post Name -->
</div>
<div class="introtext">
<a href="<?php echo get_permalink(); ?>">< ?php the_excerpt(); ?></a><!-- Post Excerpt -->
</div>
</div>
< ?php endwhile; ?>
< ?php $my_query = new WP_Query('category_name=avarice&showposts=1'); /* Get the Avarice Category's Most Recent Post */
while ($my_query->have_posts()) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>
<div class="secondcol">
<span>< ?php the_category(' '); ?></span> <!-- Category Name -->
<div class="boximage">
< ?php dp_attachment_image($post->ID, 'thumbnail', 'alt="' . $post->title . '"'); ?> <!-- Post Picture -->
<span> <a href="<?php echo get_permalink(); ?>">< ?php the_title(); ?></a></span> <!-- Post Name -->
</div>
<div class="introtext">
<a href="<?php echo get_permalink(); ?>">< ?php the_excerpt(); ?></a><!-- Smaller Post Excerpt -->
</div>
</div>
< ?php endwhile; ?>
<!-- End Wordpress Content --></div>
You’ll notice we have a bunch more PHP code in the Content section. That’s because we’ve got three loops, each getting one post from their perspective category.
The loop is how Wordpress shows posts. It takes an argument, and spits out posts, until all the posts are finished from the Query.
Reading the comments within the code, we can see how the WP_Query function gets the latest post from a specific category each time. We can then call the functions get_permalink(), the_title(), get_permalink(), and the_excerpt(); within each indidual loop.
One custom tag you may have noticed is the dp_attachment_image(); tag. That’s a custom function we’re going to write ourselves, after we finish the footer. Yes!
Step 8 – From Static to Dynamic – Finish Him!
Now we’re at the bottom of our page, the footer. The code here is very basic. There’s really not even a step involved. Just replace:
<!-- Begin Wordpress Footer -->
<br clear="all" />
<div id="footer">
< ?php bloginfo('name'); ?> is copyright with mega death enforcement by kirk "the gentle lion" kaiser<br />
< ?php wp_footer(); ?> <!-- Add footer hook for footer plugins -->
</div><!-- End Wordpress Footer -->
<!-- End #wrapper -->
Take a look at what you’ve done. The site is all ready, and hopefully by now you’re ready to populate your site. Create your custom pages, posts, and categories within Wordpress. Remember, the site template uses the wp_excerpt(); function, so you’ll need to be sure and leave an excerpt for every post that makes it on the front page.
Step 9 – From Static to Dynamic – Custom Image Code
Create a new file within your template, named “functions.php”. This will hold our custom code, and be accessible from any template file we’ve got. Copy and paste the following code into it:
< ?php
/**
* @package WordPress
* @subpackage zothcorp_theme
*/
# Displays image attachment
function dp_attachment_image($postid=0, $size='thumbnail', $attributes='') {
if ($postid<1) $postid = get_the_ID();
if ($images = get_children(array(
'post_parent' => $postid,
'post_type' => 'attachment',
'numberposts' => 1,
'post_mime_type' => 'image',)))
foreach($images as $image) {
$attachment=wp_get_attachment_image_src($image->ID, $size);
?><img src="<?php echo $attachment[0]; ?/>" < ?php echo $attributes; ?> />< ?php
}
}
?>
Our function checks our post for any attached images. It then spits out nicely formatted images according to the Wordpress settings we have for all thumbnail images. All we need to do now is change our Wordpress thumbnail settings to 375px X 175px. Then we can call this function, and have nice thumbnails for our front page automagically generated. Woohoo!
Step 10 – Tweak your code, and Keep Building
We’ve come a long way with our code. We’ve gone through a bunch of steps and come out alive. My live Wordpress site now looks like this:
Not bad, but there are flaws. The unordered list doesn’t quite look right in Safari or in Internet Explorer. A developer’s job is never over, but it’s a good time to take a step back. In Part 2, we’ll tackle CSS debugging, and putting our files into individual files, so we can show more than one page.
In the mean time, take a walk, get outside. It’s too easy to spend all your time in front of the computer, coding. The theme’s files are located here.







