The Ultimate WordPress Theme Tutorial (5)

The WordPress Theme Header Template

Posted on  by Ian Stewart

 

Now we get into the nitty-gritty: building up your header.php and validating your theme with an HTML Doctype. There’ll be a lot of PHP in this lesson but don’t despair. We’re also going to do two, essential, and kinda neat, search engine optimization tricks and start tricking out your theme with a functions.php file.

The Head Section

Right now your very blank WordPress Theme is technically invalid. That’s because it’s missing a Doctype telling the browser how to interpret the HTML it’s seeing. We’re going to use the XHTML Transitional Doctype. There are other options but right now, XHTML transitional is the best bet for a WordPress Theme.
Open up header.php and paste the following code there, before anything else.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

We’re also going to add some attributes to your opening HTML tag that will make they type of page we’re creating more apparent to the browser. Replace the current <html> tag inheader.php with the following line.

<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

Now we’re going to get into the get into the <head> section of your WordPress Theme. The<head> section contains meta-information about a web page. Typically stuff like the document title seen at the top of your browser (and in search engine results), and links to style sheets and RSS feeds.
But first open up your functions.php file. We’re going to add a little helper function there, that’ll come in handy when we’re creating the document title. It’s going to give us a page number that we can add to the title.
Start off functions.php with

<?php

and 2 lines down (I like to leave a couple of lines between functions) paste the following 2 PHP functions:

// Make theme available for translation
// Translations can be filed in the /languages/ directory
load_theme_textdomain( 'your-theme', TEMPLATEPATH . '/languages' );
$locale = get_locale();
$locale_file = TEMPLATEPATH . "/languages/$locale.php";
if ( is_readable($locale_file) )
	require_once($locale_file);
// Get the page number
function get_page_number() {
    if ( get_query_var('paged') ) {
        print ' | ' . __( 'Page ' , 'your-theme') . get_query_var('paged');
    }
} // end get_page_number

The first function tells WordPress we want to make our theme available for translation and that translation files can be found in our theme folder in a folder called “languages”. If you’re going to create a WordPress Theme you should always try your best to make sure everything is translatable. You never know when you or someone else is going to need hard-coded content available in another language.
In our next function, get_the_page_number(), you’ll see some translatable text. It looks like this:

__( 'Page ' , 'your-theme')

The text ready for translation is “Page “ followed by the directory name of our theme; in this case, “your-theme”. Pretty straightforward but there are couple other ways to write translatable text. We’ll get to them when we come to them.
Can you guess what get_page_number() is doing? If you take a look inside the function you can see that we’re checking with an IF statement to see if we’re on a paged page, you know, where you are when you click “older posts”. If you are, this function will print a bar separator and the current page number.
Also, If you’re new to PHP I want you to notice something else here. Anything after the double slash (//) is ignored and used as a comment. You’ll be seeing that a lot.
Alright, back to the <head> section of header.php.
Replace <head></head> with the following code:

<head profile="http://gmpg.org/xfn/11">
    <title><?php
        if ( is_single() ) { single_post_title(); }
        elseif ( is_home() || is_front_page() ) { bloginfo('name'); print ' | '; bloginfo('description'); get_page_number(); }
        elseif ( is_page() ) { single_post_title(''); }
        elseif ( is_search() ) { bloginfo('name'); print ' | Search results for ' . wp_specialchars($s); get_page_number(); }
        elseif ( is_404() ) { bloginfo('name'); print ' | Not Found'; }
        else { bloginfo('name'); wp_title('|'); get_page_number(); }
    ?></title>
	<meta http-equiv="content-type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
	<link rel="stylesheet" type="text/css" href="<?php bloginfo('stylesheet_url'); ?>" />
	<?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>
	<?php wp_head(); ?>
	<link rel="alternate" type="application/rss+xml" href="<?php bloginfo('rss2_url'); ?>" title="<?php printf( __( '%s latest posts', 'your-theme' ), wp_specialchars( get_bloginfo('name'), 1 ) ); ?>" />
	<link rel="alternate" type="application/rss+xml" href="<?php bloginfo('comments_rss2_url') ?>" title="<?php printf( __( '%s latest comments', 'your-theme' ), wp_specialchars( get_bloginfo('name'), 1 ) ); ?>" />
	<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
</head>

If all this looks like gobbledygook to you that’s OK. I’ll explain the main sections.
A search engine optimized title tag that shows only the post title on single posts and pages. And, of course, adds page numbers with get_page_number() on “older post” pages.

    <title><?php
        if ( is_single() ) { single_post_title(); }
        elseif ( is_home() || is_front_page() ) { bloginfo('name'); print ' | '; bloginfo('description'); get_page_number(); }
        elseif ( is_page() ) { single_post_title(''); }
        elseif ( is_search() ) { bloginfo('name'); print ' | Search results for ' . wp_specialchars($s); get_page_number(); }
        elseif ( is_404() ) { bloginfo('name'); print ' | Not Found'; }
        else { bloginfo('name'); wp_title('|'); get_page_number(); }
    ?></title>

Some meta information about our page content.

	<meta http-equiv="content-type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />

A link to our stylesheet.

	<link rel="stylesheet" type="text/css" href="<?php bloginfo('stylesheet_url'); ?>" />

A script call so we can use threaded comments when we get to our comments section.

	<?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>

A hook for WordPress plugins and other cool stuff.

	<?php wp_head(); ?>

Links for our RSS Feeds and pingbacks.

	<link rel="alternate" type="application/rss+xml" href="<?php bloginfo('rss2_url'); ?>" title="<?php printf( __( '%s latest posts', 'your-theme' ), wp_specialchars( get_bloginfo('name'), 1 ) ); ?>" />
	<link rel="alternate" type="application/rss+xml" href="<?php bloginfo('comments_rss2_url') ?>" title="<?php printf( __( '%s latest comments', 'your-theme' ), wp_specialchars( get_bloginfo('name'), 1 ) ); ?>" />
	<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

The header section

Now we want to add in our blog title, which will act as a link to our home page, blog description, and menu.
In header.php move down to the #branding div. It’s here that we’ll add in the title and description. But we’re going to do something a little different from most themes.
You’ll find that a lot of WordPress Themes tell search engines that the most important thing on every page is your blog title. They do this by wrapping it in an h1 tag; the tag that says “this is what this particular page is all about”. I, and a small group of other theme developers, think this is a bad idea. For instance, the most important thing on this page, the text that defines this particular page, is not “ThemeShaper” but “The WordPress Theme Header Template”. That’s what this page is all about after all. And on our home page, really, the most important thing is the description of our blog. It literally provides an overarching description of all the content on that page.
Luckily, this is easy to take care of.
We’re going to use WordPress’ conditional tags and some plain old HTML to code our title and blog description to do just what best practices describe. Here’s what it looks like:

			<div id="branding">
				<div id="blog-title"><span><a href="<?php bloginfo( 'url' ) ?>/" title="<?php bloginfo( 'name' ) ?>" rel="home"><?php bloginfo( 'name' ) ?></a></span></div>
<?php if ( is_home() || is_front_page() ) { ?>
		    		<h1 id="blog-description"><?php bloginfo( 'description' ) ?></h1>
<?php } else { ?>
		    		<div id="blog-description"><?php bloginfo( 'description' ) ?></div>
<?php } ?>
			</div><!-- #branding -->

So, the text of our anchored blog title is set perfunctorily in a casual div tag. Our blog description is set, using PHP IF statements and some WordPress conditional tags, either as a very important h1-wrapped description on the home page or front page or, like it’s relative the title, in a div everywhere else.
For beginners, this is a good place to step back and see what’s going on. In the code above we’re using a WordPress Template Tag called bloginfo(). You can see we’re using it to get the URL of our WordPress blog, the name of our blog, and the description. It can be used to get over 20 different pieces of information about your blog. It takes that information and prints it in your template. Understand this and you understand WordPress Themes. We take an HTML structure and we call WordPress Template Tags with PHP to fill it out. Simple stuff really. It’s just a matter of getting used to seeing the template tags in there, along with some IF statements and a few PHP loops (we’ll get to those too).
Move on down to the #access div. We’re going to add a skip link so folks using a screen reader don’t have to suffer through our menu when they just want to get to the content

				<div><a href="#content" title="<?php _e( 'Skip to content', 'your-theme' ) ?>"><?php _e( 'Skip to content', 'your-theme' ) ?></a></div>

and we’re going to add our page menu which, really couldn’t be any easier as it’s just one template tag, with only 1 argument:

				<?php wp_page_menu( 'sort_column=menu_order' ); ?>

Easy, right? So your #access div should look like this:

			<div id="access">
				<div><a href="#content" title="<?php _e( 'Skip to content', 'your-theme' ) ?>"><?php _e( 'Skip to content', 'your-theme' ) ?></a></div>
				<?php wp_page_menu( 'sort_column=menu_order' ); ?>
			</div><!-- #access -->

And that’s it! Your WordPress Theme Header Template is search engine optimized and coded up.

How To Create a WordPress Theme

This post is part of a WordPress Themes Tutorial that will show you how to create a powerful WordPress Theme from scratch. Read it from the beginning and code yourself up something awesome.