From PSD to Wordpress, Part 2

by Kirk on July 13, 2009

When we last left off in part one, we had built a complete homepage from a PSD mockup. It loaded the latest content and looked very minimal. Next, we’ll build out the rest of the pages, ending up with a complete theme we can load from within Wordpress itself.

First, we’ll create our blog post layout in Photoshop. I decided to keep a minimalist approach, consistent with the homepage. We have a quote on the left sidebar, and on the right we’ll have a list of related links.

Mocked Up Post

Step 1: Separating header and footer

This layout is easily mocked up in html. But you’ll notice, we’re reusing the header and footer parts from the homepage. As such, we should create a header.php file, and a footer.php file. This will make it easier to make changes to the header and footer in the future. If we decide to change the date, for instance, we only need to edit one file, as opposed to editing each individual template file. This is easily done, just cut and paste the code out like so:

header.php

<?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('&laquo;', 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 rel="alternate" type="text/xml" title="RSS .92" href="<?php bloginfo('rss_url'); ?>" />
<link rel="alternate" type="application/atom+xml" title="Atom 1.0" href="<?php bloginfo('atom_url'); ?>" />

<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(); ?>
</head>

<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 -->

And the footer.php file, it’s the exact same:

<?php
/**
 * @package WordPress
 * @subpackage zothcorp_theme
 */
?>

<!-- Begin Wordpress Footer -->
<br clear="all" />
<div id="footer">
<?php bloginfo('name'); ?> is powered by <a href="http://www.zothcorp.com/">zotheme</a> by Kirk Kaiser<br /><?php wp_footer(); ?>
</div>
<!-- End Wordpress Footer -->
</div>
</body>
</html>

We make sure and include the @package and @subpackage so we can keep track of which files are which. The bloginfo(‘name’); call retrieves the blog name, and the wp_footer(); is included so plugins are made aware of the footer’s location.

As we’ve taken out the top and bottom of the index.php’s file, we’ll need to make sure it loads the header and footer. Easily enough, we just need to add get_header(); to the top, and get_footer(); to the bottom of our homepage. Easy enough.

Step 2: Laying Down the Content

With the header and the footer taken care of, we only need to work on the content now. The layout of content should look something like the following:

<?php get_header(); ?> <!-- Load the Header -->
<div class="widecol">
    <h1>Truth and Lies</h1>
   <div id="dacontent">
   <div class="inlineexcerpt">
   <p>The dream and the dreamer</p>
   </div>
   <p><strong>This is some lengthy intro text.</strong> And this is some filler</p>
   </div> <!-- dacontent -->
   <div id="sidebar">
  <ul>
  <h2>Latest Posts</h2>
  <li><a href="#">The Dream</a><span><p>This is some filler.</p>
</span></li>
    <li><a href="#">The Myth</a><span><p>This is some filler.</p>
</span></li>
  </ul>
</div> <!-- #sidebar -->
</div> <!-- #widecol -->
<?php get_footer(); ?> <!-- Get the Footer -->

Save this template file, and load it in a web browser, you’ll get something like this, which is perfect:

mockuphtml

Step 3: Doing the CSS hustle

Now it’s time to begin turning this html mockup into a great looking CSS masterpiece. First, create the code to define each and every div class and get the basic layout, then follow through with the nitty gritty fonts.

.widecol {
width: 946px;
margin: 0;
padding: 0;
}

h1 a {
text-align: left;
font-size: 90px;
margin: 3em 0 0.1em 180px;
letter-spacing: -0.06em;
color: #222;
}

h1 a:hover {
color: #E86AD3;
}

.widecol h1 {
color: #222;
font-size: 7em;
letter-spacing: -0.05em;
margin: 0.5em 0 0.5em 180px;
text-align: left;
}

#content h2 {
color: #222;
font-size: 3em;
letter-spacing: -0.05em;
margin: 1em 0 0.5em 180px;
text-align: left;
}

#content hr {
margin-top: 10px;
        margin-bottom: 1em;
}

#dacontent {
position: relative;
width: 476px;
float: left;
clear: left;
margin: 0;
padding: 0 270px 0 180px;
font-size: 16px;
font-family: Palatino,Georgia,'Times New Roman',serif;
text-align: left;
line-height: 1.5em;
text-indent: 1em;
}

#dacontent strong {
font-size: 1.125em;
line-height: 1.125em;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-weight: bold;
color: #353E34;
}

.inlineexcerpt {
margin: 1em 1em 1em -180px;
float: left;
position: relative;
width: 148px;
font-weight: bold;
line-height: 1.25em;
font-family: "Helvetica Nue", Helvetica, Arial, sans-serif;
font-size: 1.4em;
}
.introtext {
background-color: #e9e8e8;
color: #000000;
border: 1px solid #d6d5ce;
font-size: 4em;
height: 175px;
text-align: left;
font-family: Arial, Helvetica, sans-serif;
padding: 30px 10px 30px 10px;
}

.introtext p {
margin: 0;
padding: 0;
}

#sidebar {
margin: 1.5em 0em 1em -184px;
float: right;
position: relative;
width: 164px;
    overflow: visible;
line-height: 1.25em;
font-family: "Helvetica Nue", Helvetica, Arial, sans-serif;
text-align: left;
}

#sidebar h2 {
font-size: 1.9em;
font-weight: bold;
        margin: 1em 0;
}
#sidebar li {
line-height: 1.25em;
list-style-type: none;
margin-bottom: 0.5em;
width: 164px;
font-size: 1.25em;
}

#sidebar a {
font-size: 1.4em;
font-weight: bold;
color: #0080C0;
text-decoration: none;
}

All of this gets inserted into your style.css file. If you’re following along, building the site out with me, you can load the non-dynamic post.php, and see how things look so far. If you’re lucky, they’ll look just like the mock up. If not, the best utility for debugging CSS errors is Firebug. Install it, then right-click, and go to inspect element. You can tweak your design live, editing CSS in place and seeing how Firefox displays. If only IE was this easy to develop in.

Step 4: Getting Jiggy with Interaction

Getting interactive is almost too easy. We start a loop, then we fetch the title, content, excerpt, and sidebar. Three easy calls, the page is completely dynamic.
single.php

<?php
/**
 * @package WordPress
 * @subpackage zothcorp_theme
 */
?>

<?php get_header(); ?>

<div class="widecol">
 <?php while (have_posts()) : the_post(); ?>

   <h1><?php the_title(); ?></h1>
   <div id="dacontent">
   <div class="inlineexcerpt">
   <?php the_excerpt(); ?>
   </div>
   <?php the_content(); ?>
   </div>

  <?php endwhile; ?>
<?php get_sidebar(); ?>
</div>

<br clear="all" />
<?php get_footer(); ?>

Step 5: Lather, Rinse, …Reuse?

Now that we’ve built out our main post, we can continue building a category.php file to display categories, and a page.php file to display pages. Easy enough, because we’ve done the hard part already.

category.php

<?php
/**
 * @package WordPress
 * @subpackage zothcorp_theme
 */
?>

<?php get_header(); ?>

 <h1><?php  the_category(' /'); ?></h1>
 <hr />

<div class="widecol">
 <?php while (have_posts()) : the_post(); ?>
   <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
   <div id="dacontent">
   <div class="inlinecatimage">
   <a href="<?php echo get_permalink(); ?>"><?php dp_attachment_image($post->ID, 'thumbnail', 'alt="' . $post->title . '"'); ?></a>
   </div>

   <div class="inlineexcerpt">
   <?php the_excerpt(); ?>
   </div>
   <?php the_content(); ?>
   </div>

   <br clear="all" />
   <hr />
  <?php endwhile; ?>

<br clear="all" />
<?php get_footer(); ?>

And finally, our page.php:

<?php
/**
 * @package WordPress
 * @subpackage zothcorp_theme
 */
?>

<?php get_header(); ?>

<div class="widecol">
 <?php while (have_posts()) : the_post(); ?>

   <h1><?php the_title(); ?></h1>
   <div id="dacontent">
   <div class="inlineexcerpt">
   <?php the_excerpt(); ?>
   </div>
   <?php the_content(); ?>
   <?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number')); ?>
   </div>
  <?php endwhile; ?>
</div>
<br clear="all" />
<?php get_footer(); ?>

If you were really paying attention, you may have noticed an earlier get_sidebar(); call. We haven’t made a sidebar.php yet. Let’s do that:

<div id="sidebar">
<ul>
<h2>Latest Posts</h2>
<?php
$myposts = get_posts('numberposts=10&offset=1');
foreach($myposts as $post) :
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title();
?></a><span><?php the_excerpt(); ?></span></li>
<?php endforeach; ?>
</ul>
</div>

This code gets the latest ten posts, with a title and an excerpt from each one. It then displays it in a list.

Step 6: Packaging it all together

Rounding out our theme, we’ll end by creating a 404.php file, which is displayed when people try to go to a page that doesn’t exist. Here’s what I came up with:

404.php

<?php
/**
 * @package WordPress
 * @subpackage zothcorp_theme
 */
?>

<?php get_header(); ?>

<div class="widecol">
<h1>Oh, Snap!</h1>
   <div id="dacontent">
    The page you were looking for isn't here. Woops!
   </div>
</div>
<br clear="all" />
<?php get_footer(); ?>

Zip the files up, and upload to your server. Activate it, and hopefully, you’ll have a brand new working theme. All in a hundred million easy steps. If only everything was this (not really) easy!

Tomorrow I’ll upload a complete theme file, including all the PSD source files. You can have it and play with it as much as you like, it’ll be a completely free release. Until next time…

  • Please post the final files! Great tutorial but last step was missing! Thanks in advance!
  • kudzai
    This is amazing! Thanks.
  • thanks I'll read A-z and try my-own
  • wow nice blog!Please visit back my blogthank you :)
blog comments powered by Disqus

Previous post:

Next post: