Try Tuts+ Premium, Get Cash Back!
DIY WordPress Framework Part 2: Creating the Theme

DIY WordPress Framework Part 2: Creating the Theme

Tutorial Details
  • Platform: WordPress
  • Estimated Time: 5 -10 minutes
  • Difficulty: Beginner - Intermediate
This entry is part 2 of 4 in the series DIY Theme Framework

When I last left you, we had looked at some design principles, explored other frameworks, and came to the inevitable conclusion that we’d build our own. In this tutorial, we’re going to cover the steps I took to create what I called my WordPress Boilerplate, taking a close look at the CSS, functions.php, and select template pages.

The important thing to keep in mind throughout development is we want to keep this general enough that we can easily adopt it/build on it in future themes; I also made it a personal goal of mine to make this good enough to stand along as it barebones theme. Let’s remember that going forward.


The Theme’s CSS

The first thing we need to do is arrange the CSS. There are 2 main components to the CSS in my WordPress Boilerplate: style.css, which is required, and the /css/ folder, which includes all of the CSS for the framework. In style.css you’ll find two sections: The theme definition and the calls to my actual CSS. The entire style.css file looks like this:

/*
Theme Name: WordPress 3.0 Boiler Plate
Theme URI: http://casabona.org/
Description: A Boiler Plate  Theme for WP 3.0. Now with more HTML5!
Version: 1.5
Author: Joe Casabona
Author URI: http://www.casabona.org
*/
@import url("css/reset.css");
@import url("css/master.css");
@import url("css/ie.css");

After the theme definition, you see three @import lines. This is where all of the heavy lifting for the CSS goes. reset.css is obviously the CSS reset. I actually recently changed this to use normalize.css for a few reasons. The first reason is that instead of resetting everything to a default, unformatted style, it creates styles that you’d expect from a default browser. For example, in a standard reset, <strong> is no longer boldface type. In normalize.css, it is. The second reason is that it has default styles for HTML5 elements, which are necessary for older browsers that don’t support the new ones.

Note: I use HTML5 in this theme. It works in Firefox, Chrome, Safari, and IE7-9.

After reset.css is called, I call my main stylesheet, master.css (naming conventions thanks to Dan Cederholm of SimpleBits). This is crux of the matter! All of my post-reset default styles will be here. I won’t paste all of the CSS here, but I have included the files for you to view. In creating the CSS, I kept in mind styles that usually stay the same for me from site to site; things like the width of the overall container, my navigation styles, how I arrange my sidebar, etc. I also generally use padding/margins in multiples of 15 for my paragraph and list elements, so I have some basic definitions for those too.

I also include default styles for some common WordPress classes, including ones generated by the WordPress editor. They are: .navigation, .post, .postmetadata, ol.commentlist, ol.commentlist li, ol.commentlist li .vcard, ol.commentlist li .vcard img, form#commentform, form#commentform p label, form#commentform input, form#commentform textarea, form#commentform textarea, form#commentform input[type="submit"], img.centered, .alignright , .alignleft, .aligncenter, div.aligncenter, .wp-caption , .wp-caption img, .wp-caption p.wp-caption-text.

The last thing I include in master.css is a class that will make divs “self-clearing.” That is, it will eliminate the need for a .clearfix div (again, thanks to Dan Cederholm for this).

/* self-clear floats */
.group:after {
	content: "."; 
    display: block; 
    height: 0; 
    clear: both; 
    visibility: hidden;
}

After master.css is called, I call in the final piece of our puzzle, ie.css. This is where any and all IE fixes will go. Right now, it’s just a fix for .group and a PNG fix. Keep in mind that the import order is very important here, as some things may get overridden, and changing the order may mess with the styles we’ve defined.


Functions.php

Just as important as the CSS stuff is the functions.php file. This is where we will add any general functions we plan to use throughout the theme, as well as any definitions for sidebars, menus, and more will go. I start this off with two lines:

define( 'TEMPPATH', get_bloginfo('stylesheet_directory'));
define( 'IMAGES', TEMPPATH. "/images"); 

These are two constants I use quite frequently throughout the theme. The first one is the template’s path; this is good for referencing theme specific files. I used ‘stylesheet_directory’ instead of ‘template_directory’ because if we use this as a parent theme (tutorial coming soon), ‘template_directory’ would grab the wrong path (namely this one instead of the child’s path). The second line actually uses TEMPPATH to create a path to the /images/ directory, which we’ll also use very frequently, whether it be in this theme or in child themes.

After these two lines, I add support for dynamic menus and 2 widgetized sidebars; one is the primary sidebar, and one is a 2nd “just in case” sidebar. Generally I will use it in my theme’s footer. Finally, I created two other functions that I found I was using regularly:


function print_post_nav(){
?>
		<div class="navigation group">
			<div class="alignleft"><?php next_posts_link('« Next') ?></div>
			<div class="alignright"><?php previous_posts_link('Previous »') ?></div>
		</div>
<?php

}

function print_not_found(){
?>
		<h3 class="center">No posts found. Try a different search?</h3>
		<?php get_search_form(); ?>
<?php
}

The first one prints the post’s navigation and should be used outside the Loop. That means we can use it on any page that lists posts (index, search, and any custom post type template). The second function creates the “Posts not found” area, which I was using on almost every template page.

There is, of-course, no limit to how many functions you create here. These were just the ones I was using frequently.


Template Pages

Next up are the template pages. We’ll look at 4 specific pages: header.php, footer.php, single.php, and page.php. The others are basically derivatives of the page or single templates.

Header & Footer

Below is our entire header.php file:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US"> 
 
<head> 
<title><?php bloginfo('name'); ?> | <?php wp_title(); ?> </title>
<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

<!--[if lt IE 9]> <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]-->

<?php wp_head(); ?>
</head>
<body>
	<div id="container" class="group">
	
		<!--Header - Name of Item Here-->
		<header class="group">
			<h1><a href="<?php bloginfo('home'); ?>"><?php bloginfo('name'); ?></h1>
			
			<nav>
				<?php wp_nav_menu( array('menu' => 'Main' )); ?>
			</nav>
		</header>

		
		<!-- End Header -->
		
		<!-- Main Area -->
		<?php get_sidebar(); ?>
		
		<div id="content" class="group">

You can see that aside from our regular <header> declarations, there isn’t too much. I include <!--[if lt IE 9]> <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> to ensure our theme is HTML5 ready, and then in the body, create a basic header with the site’s name and navigation, call the sidebar, and start the “content” area, all wrapped in out predefined #container div. You can see that the way I lay things out is consistent with how my CSS is define (for example, the sidebar, which I float right, is above the main content area).

Note: I’m not talking about the sidebar.php template because it’s the same as every standard sidebar: check to see if a widget area is defined; if not, print some default widgets.

The same goes for our footer:

<?php print "\n\n"; ?>

</div>

<!--Footer Information--> 
		<footer class="group"> 
		
			<?php if ( !function_exists( 'dynamic_sidebar' ) || !dynamic_sidebar('Sidebar2') ) : ?>
			<?php endif; ?>
			
			<p>© <a href="<?php bloginfo('home'); ?>"><?php bloginfo('name'); ?></p>
		</footer> 
		<!-- End Footer Information --> 
		
	</div> 
	<!--end container--> 
	
	
	<?php wp_footer(); ?>
		
</body>
</html>

I print two line breaks, mostly to make the code look pretty, end the content div, then start on the footer. I include the secondary sidebar in the footer as this is something I often do, then have some general copyright info, and round out the theme by closing any open tags. Again, I try not to do too much with the footer since this is a framework, but I do provide some options to add info to the footer if I need to.

Single & Page

These files are also pretty basic. I tried to cut out most of the stuff that’s not needed while leaving in the information you’d expect to see on each. single.php should look familiar:

<?php get_header(); ?>

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

		<div <?php post_class() ?> id="post-<?php the_ID(); ?>">
			<h2><?php the_title(); ?></h2>

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

				<p class="postmetadata alt">
					<small>
						Posted on <?php the_time('l, F jS, Y') ?> at <?php the_time() ?> | Category <?php the_category(', ') ?> | <?php the_tags( 'Tags: ', ', ', '|'); ?>
						<?php if ( comments_open() && pings_open() ) {
							// Both Comments and Pings are open ?>
							<a href="#respond">Comment</a> |

						<?php } elseif ( !comments_open() && pings_open() ) {
							// Only Pings are Open ?>
							Comments are currently closed | 

						<?php } elseif ( comments_open() && !pings_open() ) {
							// Comments are open, Pings are not ?>
							<a href="#respond">Comment</a> | 

						<?php } elseif ( !comments_open() && !pings_open() ) {
							// Neither Comments, nor Pings are open ?>
							Both comments and pings are currently closed. | 

						<?php } edit_post_link('Edit this entry','','.'); ?>

					</small>
				</p>
			</div>
		</div>

	<?php comments_template(); ?>
	
	<div class="navigation group">
			<div class="alignleft"><?php previous_post_link('« %link') ?></div>
			<div class="alignright"><?php next_post_link('%link »') ?></div>
		</div>

	<?php endwhile; else: ?>

		<?php print_not_found(); ?>

<?php endif; ?>
<?php get_footer(); ?>

We have the header and footer, and our loop. I kept the classes that are common among most WordPress themes so that people who use this can just define those classes in the CSS without having to change the single.php template. I also include the standard post meta data and a comments area. Notice I don’t use the post navigation function I write in functions.php. That’s because this is inside the Loop, and that function would behave unpredictably.

The page.php template is a bit shorter:

<?php get_header(); ?>
	<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
		<h2><?php the_title(); ?></h2>

			<?php the_content('<p class="serif">Read the rest of this page »</p>'); ?>

			<?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number')); ?>

	<?php endwhile; endif; ?>
<?php get_footer(); ?>

Again, I include only what’s needed. There are no extra classes or information. The pages on websites focus on content, which is why I tried to streamline this template as much as possible.

Other Templates

Obviously I can’t cover each template page here; I suggest you check the included source. For each template I tried to cut away what I wasn’t using, and in some cases, I left templates along (as WordPress’ default info). Since we all code differently the way I add things might not suit you best, but I did try to make this as general as possible.

Here is what the theme looks like out of the box:


The WordPress Boilerplate Theme

Conclusion

So here’s an overview with some examples of creating a theme framework. Looking at my sample code, you can see that I didn’t try to do too much with any single template file. If I am going to add anything to this theme, it will be in the functions.php file because the template files should be left basic- especially if we are just going to overwrite them when creating a child theme. Speaking of, that’s what we’ll be doing next time, so stay tuned!


Other parts in this series:DIY WordPress Theme Framework Part 1: Defining Your NeedsDIY WordPress Framework Part 3: Using the Framework as a Child Theme
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Connor Crosby

    Excellent read! And this is very helpful :) Keep ‘em coming, Joseph.

  • dj

    Very interested in this as I’ve recently decided, after many years, to take the plunge and learn WP and am now comfortable enough to begin wanting to code pages like I want them to look. I’ve spend more time than I probably should have in picking through the WP default theme to see how it works and spent most of it confused. However, a couple of differences I notice, and hope you can explain.

    1- SEO is very important to me and understand that the hierarchy of the HTML on the page is extremely important to spiders. Placing your sidebar at the top before loading anything else means that it is the MOST important content from an SEO standpoint. That is why, as I understand it, nearly everyone loads it AFTER loading the main content, including the WP default theme. From a CSS standpoint I suspect it’s easier to do it the way you do it – and in fact that used to be the way I did it too when I was learning HTML. Is that an oversite or have things changed?

    2- You’ve said a couple of times: “I have included the files for you to view.” I don’t see them anywhere – do you mean that you’ve included them for “premium users only?” or am I missing a link to somewhere. I do see the link to Gallager’s “normalize” but not to yours. Can you give a link to them please?

    • http://cssrockstar.com matt

      I wouldn’t put the sidebar first either. You could use the same code and just move the sidebar code to the top of the footer.php file.

    • http://razerdesign.com Kevin

      Yes, the only way files should be able to be accessed is through Premium Membership, unless you see a demo or project files link at the top of the article as per Envato’s conventions.

    • http://www.casabona.org/blog/ Joe Casabona
      Author

      I wouldn’t say I’m an SEO guy (more of a coder), but I generally feel that while order is important, I feel semantically correct HTML/CSS contributes much more to SEO, especially now that there are HTML5 elements like header, footer, aside, and article that specifically define the content sections.

      • dj

        NOPE… it’s content – plus the self-centered idiosyncrasies that Google foists on us through their algorithms: Keyword in header, keyword in title, keyword in content copy (but not too many) – and now apparently, how recent the page was published! The spiders do NOT read every word in the posted page – only the top n? many – they aren’t sayin’. INCOMING links are important – outgoing probably very little (except to those you link too); however, it wouldn’t surprise me if having too many outbound links detracted from your score (and/or even the placement of your links within you page).

        It is NOT a good idea to have superfluous content (ads, links, comments, legal disclaimers and other crap) be the first thing that the Google bot sees on your page. [In fact, if it were me, I would make the change to the source script because this seems to be a basic "best practice" of substantial importance to those worried about rankings]. Perhaps, as others have suggested, to the footer.php – with the requisite alterations to the css.

        Thanks for adding the source files. All this said, I AM interested in seeing how you flesh out the rest of the project. As this is a “framework” it would be important to follow best practices in not only coding but other “meta” techniques and procedures as well.

  • http://socialmarketingandtraining.com Philip

    Where is the source files located. I’m curious how you constructed the sidebar.php file.

    Phil

  • http://cssrockstar.com matt

    I feel sort of web uncool for asking but is !html a valid doctype now?

  • binarymac

    download file? demo? or am i just completely blind

  • Greg

    Great start so far,

    just think the doctype for HTML5 is
    ” ”
    //to force the charset

    • Greg

      HTML5 doctype and charset

  • http://titan-creative.net S3bY

    Nice framework! I can’t wait for the child theme tutorial!

  • http://www.logicdesign.co.uk/ Website Design Suffolk

    Some rearly usefull tips here, creating an html5 frameworks is on every wp developers to do list. defining file paths in the function.php is an idea i’ll definatly start doing – very helpfull.

  • http://www.nomad-one.com nomadone

    Thanks again Joseph, all makes alot of sense. We should definitely be more methodical as we end up repeating the same processes over and over again when it comes to theme development.

    I noticed you mentioned the source but there don’t seem to be any links for downloading it anywhere unless I missed it the few times I scanned over the article.

  • http:publisherwarrior.com alfi

    Easy to follow.. building framework will bring my WordPress skill to the higher level.. update ASAP please..

  • http://clearconceptsdesign.com jowens

    I’m really enjoying this tutorial series! But I have to echo the others in saying that I can’t find the source files. Are we missing something?

  • http://www.casabona.org/blog/ Joe Casabona
    Author

    Hey Everyone,

    Sorry about the files! They were attached but got kicked out for some reason. They are there now!

    I do believe I have a mistake in the DOCTYPE definition, however. It says &;lt;!html> where it should say &;lt;!DOCTYPE html>

  • http://clearconceptsdesign.com jowens

    Thanks for adding the files!

    I’m not sure why, but the WP admin bar is messed up when I test the plain wp-boilerplate theme. The bar is positioned properly, but the menu items are below the bar… not sure what is causing that.

    • http://clearconceptsdesign.com jowens

      Hmmm… changing the CSS for “#wpadminbar .quicklinks a” to height: auto; fixes the problem. Any idea why the theme is causing problems with WP 3.1′s admin bar? It’s an easy fix, but it makes me think there is probably something somewhere in the theme that is causing the issue that should be correctable without having to mess with the admin bar CSS.

      • http://www.casabona.org/blog/ Joe Casabona
        Author

        Hmm That’s interesting- I’ll have to look into it. I’m guessing there is something in normalize.css (the reset) that’s doing it.

      • http://jamesgrubb.co.uk James Grubb

        I just submitted a post about updating the deprecated bloginfo(‘home’) to home_url() and in header and footer and missing closing anchor tag in the footer. It seems to have fixed the admin bar issues.

        • http://jamesgrubb.co.uk James Grubb

          just checked, it is the missing closing anchor tag in the footer copyright line thats messing up the admin bar

  • http://www.yourdigitalspace.com Swamykant

    Easy to follow tutorial. Great work.

  • Pingback: Создаем фреймворк темы для WordPress своими руками: практика | Wordpresso

  • http://about.me/ziadrahhal Ziad Rahhal

    If using HTML5, why did you write:

    instead of: <html >

    I suppose HTML5 wanted to get rid of xml stuff. Am I missing something you wanted to do on purpose?

    And by the way, I advise to add a <meta charset="”> before the

    • http://about.me/ziadrahhal Ziad Rahhal

      All the html that I wrote disappeared.

      If using HTML5, why did you write: <html xmlns=”http://www.w3.org/1999/xhtml” dir=”ltr” lang=”en-US” >

      instead of: <html <?php language_attributes(); ?>>

      I suppose HTML5 wanted to get rid of xml stuff. Am I missing something you wanted to do on purpose?

      And by the way, I advise to add a <meta charset=”<?php bloginfo(‘charset’); ?>”> before the
      <title>

  • http://about.me/ziadrahhal Ziad Rahhal

    in “single.php”, why you didn’t use function print_post_nav() that you implemented in “functions.php” instead of rewriting its code again?

    It is nice to use it though in order to show a reuse use case.

  • Pingback: DIY WordPress Framework Part 4: Using the Framework as a Boiler Plate | Wptuts+

  • Pingback: My Stream » DIY WordPress Framework Part 4: Using the Framework as a Boiler Plate

  • http://jamesgrubb.co.uk James Grubb

    Thanks for the framework. Couple of issues came when using WP Debug bloginfo(‘home’) is now deprecated and should read home_url() or home_url(‘/’) this effects header and footer.

    Additionally currently footer code …
    © <a href="”>

    i think should be …
    ©<a href="”>

    missing closing nchor tag

  • http://jamesgrubb.co.uk James Grubb

    sorry code not diplaying correctly

    footer should read:

    <a href="”>

    Footer is missing ‘echo’ and closing anchor tag

    download code reads:

    © <a href="”>

  • http://jamesgrubb.co.uk James Grubb

    Apologies my code is still not displaying correctly. The footer is missing ‘echo’ and closing anchor tag.

  • http://www.budestrings.co.uk jan

    I think I’m having the same problem described above by jowens, with menu items floating below the admin bar. where do I apply the fixes described by jowens and/or james grubb, please? any help would be massively appreciated by this rookie. just let me know if i need to copy and attach any code.

    Thanks in advance, Jan

  • Jan
  • http://www.dragonsdesign.co.uk Chris Ward

    Great tutorial, thanks. I use a modded version of Aaron Groggs boilerplate theme http://wordpress.org/extend/themes/boilerplate, which has html 5, html 5 boilerplate, css resets and a lot more features, i’ve also added the 960 grid, it’s a great bare bones theme to start with.

  • Pingback: Tweet-Parade (no.45 Nov 2011) | gonzoblog.nl

  • http://twitter.com/NickkkNames NickkkNames

    Nice article. Will try to build my next project http://nickkknames.com with this boilerplate