8 Top Tips for Wordpress Theme development

Having moved this blogs CMS from ExpressionEngine to Wordpress 2.7 , I wanted to design and develop my own theme. You can start from blank canvas themes however I chose to start completely from scratch primarily so that I could get a good idea about how things work in Wordpress.
I did hit a few roadblocks during development and what follows are a few tip that could help you out if your creating your own theme.
Adding a body tag ID dynamically
There are times when it’s really useful to alter styling between pages using an ID on the body tag that can then be targeted via CSS. In Wordpress this get’s a little tricky as pages are repurposed like single.php. So I created a new function in my functions.php file to dynamically assign preset ID’s to selected pages.
function jmw_body_class( $print = true ) { global $wp_query; $c = ""; // Generic semantic classes for what type of content is displayed is_archive() ? $c = 'bpgArchive' : null; is_date() ? $c = 'bpgDate' : null; is_search() ? $c = 'bpgSearch' : null; is_paged() ? $c = 'bpgPaged' : null; is_page() ? $c = 'bpgPage' : null; is_page('Journal') ? $c = 'bpgJournal' : null; is_page('About') ? $c = 'bpgAbout' : null; is_page('Projects') ? $c = 'bpgProjects' : null; is_page('Contact') ? $c = 'bpgContact' : null; is_single() ? $c = 'bpgPost' : null; in_category('4') ? $c = 'bpgJournal' : null; //Single page for Journal entries in_category('11') || in_category('8') || in_category('10') ? $c = 'bpgProjects' : null; is_home() ? $c = 'bpgHome' : null; // For the blog posts page, if set is_404() ? $c = 'bpg404' : null; // CSS does not allow a digit as first character return $print ? print($c) : $c; }
You would call this from your header.php template file like this:
<body id='<?php jmw_body_class( ) ?>'>
The code should be clear, what we are doing is using Wordpress’s functions to determine what page is being called. The standard ones are there, then I have added my own specifically for this site. I have page files like Journal and Projects that I can identify using the is_page() function.
Watch the order of items. This is because is_single() will fire for every single page and as I have separate single pages depending upon the category of the post. So by adding an in_category() rule after is_single() I can target the singles page for those category posts.
Better SEO page titles
It’s always a good idea to have the best semantic page titles you can. For SEO purposes your title tag should be unique to each page, so you want to include things like the post title, what page you are on if your paging through archives and possibly your sites name.
I always place my site name at the end of any title, apparently this is better for the likes of Google but more importantly better for people bookmarking your page – the content is described first followed by your sites name.
So like the example above it’s into your functions.php file to add something similar to:
function jmw_page_title( ) { global $paged; $c = ''; // is the current page a tag archive page? if (function_exists('is_tag') && is_tag()) { // if so, display this custom title $c = 'Tag Archive for "'.$tag.'" - '; // or, is the page an archive page? } elseif (is_archive()) { // if so, display this custom title $c = 'Archive for '.wp_title('',false); // or, is the page a search page? } elseif (is_search()) { // if so, display this custom title $c = 'Search for "'.wp_specialchars($s).'" - '; // or, is the page a single post or a literal page? } elseif (!(is_404()) && (is_single()) || (is_page())) { $c = wp_title('',false); // or, is the page an error page? } elseif (is_404()) { // yep, you guessed it $c = "opps, sorry I'm a 404 error page - "; } elseif (is_home()) { $c = get_bloginfo('name') . ' - ' . get_bloginfo('description'); } //Shows what page your on if ( $paged >= 2 ) { $c .= " page ". $paged; } // finally, display the blog name for all page types if (!is_home()){ $c .= $pagenum . ' » ' . get_bloginfo('name');} return print($c); }
The just include the following PHP in your header.php file:
<title><?php jmw_page_title();?></title>
Take a look at the title’s on this site for an example of how this works.
Load category specific single post page
This is covered by many other Wordpress theme blogs. I wanted to have a differently structured page for my single project posts compared to my single journal posts. Wordpress will naturally open up single.php when asked to serve up a single post.
The key is to remove all content from the single.php page and include the appropriate single page depending upon the post category:
<?php // Journal entries if ( in_category('4') ) { include(TEMPLATEPATH . '/single-journal.php'); } //Projects elseif (in_category('11')) { include(TEMPLATEPATH . '/single-projects.php'); } ?>
This is small but the theory is that you can have differently structured pages for each category if you so wished. It’s worth saying that if you have the same page structure and you just wanted to load up different CSS just follow the same principle above.
Fixing the more tag
When it comes to limiting a posts output like on the homepage, you use a number of methods. There is the standard the_excerpt or the common the_excerpt_reloaded (plugin) or you could just use the more option. Many themes use the_excerpt_reloaded to limit content based upon character length and tags whilst still retaining valid XHTML tags. This didn’t work exactly how I wanted so I reverted back to using the more option in the Wordpress editor.
Problem was it was failing within some of my custom loops. So here is a fix that works:
<?php //Fix to get the more tag to work properly global $more; $more = 0; the_content(""); ?>
Using additional stylesheets
As a good web developer you will no doubt have the need to include more than one style sheet into your theme. A standard Wordpress theme will have style.css in the theme folder root and you could use the @import rule in that CSS file to load extra style files for modern browsers. However you may want to include a print or handheld media stylesheet or even use IE conditional comments for loading in additional CSS.
Simple you just need to get the URL address path for your theme at runtime:
<link rel="stylesheet" type="text/css" media="print" href="<?php echo get_template_directory_uri(); ?>/styles/print.css" />
Target the first post in a list
Using the loop you can style or alter the markup for the first post (or any number in reality). This might be useful in your theme to allow more text or have a larger layout than the rest of the posts in alist.
This is easily done without using any plugins like this, add a new php variable before your loop code ($count in this example):
<?php query_posts('cat=1&showposts=5&order=DESC'); ?> <?php $count = 1; ?> <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
Now in your code for writing out the content you can use that new variable in a conditional, not forgetting to increase the counter afterwards:
<?php if ($count == 1) : ?> // You different code for the first post goes here <?php else : ?> // If the count is greater than 1 then this will be used <?php endif; $count++; ?>
Fixing broken paging links
Depending upon your permalink structure Wordpress (at least with version 2.7) can break your paging links at the bottom of a post. This solution worked although I could not get it to fully work when using a custom homepage. If you have any suggestions please leave them in the comments.
When calling your custom query pass through a page variable:
<?php query_posts('cat=4&posts_per_page=5&paged='.$paged); ?>
Wordpress security
SmashingMagazine.com recently had a great series of articles on how to make your Wordpress installation more secure. I have followed a number of these suggestions, they are well worth a look.
In following one of the suggestions to rename your table prefix from wp_ to something a little more obscure and random, I hit a bit of trouble. Basically this should ideally be done when you first install wordpress. However I had already start my Wordpress site so had to do it retrospectively.
Following this guide, I managed to change the database tables. However I could not log into the admin interface. To get around this you also need to change any values inside wp_options table, look for wp_user_roles and change the wp_ bit to your new table_prefix.
In conclusion
I have really enjoyed working with Wordpress on my site redevelopment. ExpressionEngine was becoming very clunky and is starting to show it’s age, the new EE2.0 has some tough competition. With some tweaking Wordpress is very capable as a CMS. It is not without it’s oddities and some of the UX in the admin area is a little questionable. But if you fancy rolling up your sleeves and getting dirty with a bit of PHP then you can achieve great things with Wordpress.
Leave a response, or a trackback from your website
6 Comments so far (rss)
jmwhittaker said:
If your planning to work from scratch on a Wordpress theme then you might be interested in WP Framework.
.
on February 23rd, 2009 at 9:40 am
Andy Potanin said:
Awesome list, thanks.
on March 13th, 2009 at 12:59 am
Adam said:
“Target the first post in a list” – I’ve only been playing with wordpress themes today – and I’m amazed how much I could get done quickly – the only issue I’ve come up against might be answered by this para in your document. However I’m struggling to make the link. I want to extract the first few sentences from the most recent post, with a link to its full page. Would following this be the right track?
on April 15th, 2009 at 9:27 am
jmwhittaker said:
Hi Adam, yes you could do exactly that. What you would need is to then inside the code for the first post only is to output either a excerpt or trim the post using the more tag inside the actual post. Failing that you can get a plugin called the excerpt reloaded. This allows fine control over what is and isn’t displayed from your post. Have fun.
on April 15th, 2009 at 12:16 pm
Gary said:
Thanks on the tip for targeting the first post. My question is, how would you get a certain post to show at the top of ALL pages in a particular category? Not just the first page, but every page thereafter? Basically I have a small graphic that goes at the top of the page ( where the posts are listed ) thats shows depending on which category you are in. So on every page, the first post would be the post with the category graphic, followed by the normal posts for that category. Appreciate any insight you could lend! THanks
on April 21st, 2009 at 6:41 pm
250 Wordpress Tutorials said:
[...] 60. 8 Top Tips for Wordpress Theme development [...]
on April 30th, 2009 at 4:36 pm
Leave a response