Today I want to go over some of the do’s and don’ts of WordPress theming. Regardless if you’re building a WordPress theme for yourself or if you’re building one for release so others can use it, you should be following these do’s and don’ts as closely as possible.
1. Do not hard code full URL’s into your themes
When you’re building your themes, there may be times where images are used, for social media icons or RSS feed icons, and during these points in your coding, you may want to code the full url out (ie: /wp-content/themes/your-theme-name/images/image.jpg) but this will cause errors in the website whenever the person using your theme changes their theme folder name.
The proper codes to use in order to pull the full URL’s dynamically are below.
<?php bloginfo('stylesheet_directory'); ?>/images/image.jpg
2. Do utilize the template tags as much as possible
WordPress does an awesome job of laying out all of the template tags you can use, so do yourself a favor (as well as the rest of the people who may use your themes) and learn the WordPress template tags – then utilize them as much as possible. By using template tags, you’re able to ensure that your themes don’t break or cause errors when the end user sets it up and gets it running.
3. Do not forget navigation drop down codes
When you’re building your WordPress theme, one item that seems to be overlooked is the drop down codes for your navigation. Sure, some themes might have the navigation set up to not utilize the multi level ul’s, keeping everything in one single row, but what about for those of us who have multiple child pages for each main parent page?
There’s a solution for that. You can check out some of the tutorials below on how to code multi-level drop down menus.
- How to implement a perfect multi-level navigation bar
- Multi-level drop down navigation menus: Examples and tutorials
- Multi-level menus with jquery and css
4. Do make your theme widget ready
In my opinion, as an end user, there’s nothing worse than deploying a theme and getting ready to set everything up, only to notice that I am now faced with the task of trying to customize sections of my themes by hard coding information into them. Your sidebars and various other places in your theme (do you have a three column footer? widgetize it!) should be as easy to edit as possible. It’s one of the easiest things to do to your themes, and will benefit your theme’s users a lot.
Automattic has a great tutorial on how to widgetize your theme. Check it out here.
Also be sure to check out the widgetizing themes tutorial here at Theme Lab.
5. Do not make users rely on numerous plugins for your theme to work
If you’re releasing themes for free or creating commercial WordPress themes, you should take your end users best interest into play with you’re building your themes. Cluttering your themes with 5-10 needed plugins will not only cause people to be frustrated when downloading and setting up your theme on their site, it will also cause a lot of people to not download it at all because, lets face it, people don’t have attention spans of more than 2-3 seconds.
For instance, if you’re going to set up pagination in your theme, why not utilize this article to learn how to set it up in your theme automatically. Cats Who Code has a pretty good tutorial on how to add pagination into your theme without needing to activate a plugin.
6. Do show the search term on the search results page
For some reason, this is an often overlooked tip that you can (and should) implement into your themes. It’s a simple, one line code that allows your theme to remind the visitor what they just searched for. It may seem trivial, but it is helpful so if the results bring back zero posts, the visitor knows the exact phrase they searched for and can then type in a different search term.
Below is the code used to replace your current “Search Results” title in your theme.
<h2>Search Results for <em><?php the_search_query() ?></em> </h2>
7. Do not half ass your 404 error pages
Instead of just leaving your 404 page to say “404 – page not found”, why not give your visitors some more options? Adding in a category list, recent posts, popular posts, a search box and (if you’d like to monetize your 404 page) an advertisement can give your 404 page some spice compared to the dull, useless ones found in most WordPress themes.
If you’re looking for 404 page inspiration, Smashing Magazine has a killer showcase of 404 pages from around the web that is worth checking out.
8. Do make sure you have all of the basic files in your theme folder
When you’re building a WordPress theme, making sure you can customize it as much as possible right from the get-go is essential. Starting out with an index.php, header.php, sidebar.php and footer.php file combo might seem like a good idea to the minimalists out there, but I’d suggest starting out with all of the basics below in order to give you a bit more control over what is displayed – when, where and how.
- style.css
- header.php
- index.php
- sidebar.php
- footer.php
- single.php
- page.php
- comments.php
- 404.php
- functions.php
- archive.php
- searchform.php
- search.php
For more information about these template files and what they do, check out the template hierarchy page on WordPress.org.
9. Do not forget the RSS integration
When you’re building your blog, one of the items that draw peoples attention the most is the ability to subscribe to your blog via an RSS reader. So, instead of requiring your theme users to add this information in themselves, why not take the steps to add in a subscribe to rss box just like you do the search box. Add a RSS button, a subscribe via email option and you can also even add in the subscriber count in text by adding this bit of code to your theme where you’d like it to be displayed (replace “feedburner-id” with your own FeedBurner ID – if you’re releasing this theme in the wild, take a look at #11 on our list and make sure you have this as an option).
<?php //get cool feedburner count $whaturl="http://api.feedburner.com/awareness/1.0/GetFeedData?uri=feedburner-id"; //Initialize the Curl session $ch = curl_init(); //Set curl to return the data instead of printing it to the browser. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //Set the URL curl_setopt($ch, CURLOPT_URL, $whaturl); //Execute the fetch $data = curl_exec($ch); //Close the connection curl_close($ch); $xml = new SimpleXMLElement($data); $fb = $xml->feed->entry['circulation']; echo $fb; //end get cool feedburner count ?>
10. Do add CSS styles for threaded comments
If you’re building a theme, you should always be prepared for threaded comments. It’s a feature in WordPress that a lot of blogs use in order to build interaction in their comments section. So, preparing your stylesheet for threaded comments is a great idea. Chris has a great post on CSS codes for the default CSS classes that WordPress spits out in their comments section, giving your theme a stylized comments section without needing to touch the comments.php file.
11. Do not release a theme without an options panel
Some people might not agree with this, but I believe it’s a part of the natural progression of WordPress theming. If your theme isn’t running some kind of WordPress options panel with the ability to edit, customize and change items in your theme without having to edit codes, you’re doing something wrong.
If you’re not sure how to go about creating your own theme options panel, the links below will show you how to do it.
12. Do make sure your themes work out of the box
This goes hand in hand with #5 on out list – you should always make sure your themes work right out of the box. Some themes I’ve seen require 5-6 steps before the theme is workable on the site, including, but not limited to, plugin activation and theme option panel editing/saving. If the theme requires certain things, make sure there’s a backup default item used.
For instance, in your theme options panel you’re building and/or using, make sure there’s default information in each section, so things are showing up, regardless if the end user has updated them or not. The same goes with plugins, if you’re using a WordPress pagination plugin in your theme, why not code it in so that the theme reverts back to the previous/next links if the plugin isn’t active.
13. Do not make excessive use of custom fields
Yes, most magazine style WordPress themes from a couple years ago were built utilizing custom fields at every turn, but most people will not want to actually fill out 3, 4 or 5 custom fields for each post. So, make things easier for them. If you’re going to show an image from the post on the home page of your theme, take this handy piece of code and add it into your themes functions.php file and it will automatically the posts first image, without the need of a custom field.
// Get URL of first image in a post
function catch_that_image() {
global $post, $posts;
$first_img = '';
ob_start();
ob_end_clean();
$output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
$first_img = $matches [1] [0];
// no image found display default image instead
if(empty($first_img)){
$first_img = "/images/default.jpg";
}
return $first_img;
}
Once you’ve added that code in, just add <?php echo catch_that_image(); ?> in your theme’s files wherever you’d like the image to show up.
Thanks to the good ol’ WordPress support forums for this handy tip.
14. Do SEO your <title> tag
A great way to ensure your theme is as SEO ready as possible is to remove the default <title> tag found in your themes header.php file and replace it with the codes below. It will give your theme’s titles a bit more juice and help the SEO efforts that your themes users will want to put into practice – all without requiring them to touch a thing.
<?php if ( is_home() ) { ?><? bloginfo('name'); ?> | <?php bloginfo('description'); ?><?php } ?> <?php if ( is_search() ) { ?>Search Results for <?php /* Search Count */ $allsearch = &new WP_Query("s=$s&showposts=-1"); $key = wp_specialchars($s, 1); $count = $allsearch->post_count; _e(''); echo $key; _e(' — '); echo $count . ' '; _e('articles'); wp_reset_query(); ?><?php } ?> <?php if ( is_404() ) { ?><? bloginfo('name'); ?> | 404 Nothing Found<?php } ?> <?php if ( is_author() ) { ?><? bloginfo('name'); ?> | Author Archives<?php } ?> <?php if ( is_single() ) { ?><?php wp_title(''); ?> | <?php $category = get_the_category(); echo $category[0]->cat_name; | <?php bloginfo('name'); ?><?php } ?> <?php if ( is_page() ) { ?><? bloginfo('name'); ?> | <?php $category = get_the_category(); echo $category[0]->cat_name; ?>|<?php wp_title(''); ?><?php } ?> <?php if ( is_category() ) { ?><?php single_cat_title(); ?> | <?php $category = get_the_category(); echo $category[0]->category_description; ?> | <? bloginfo('name'); ?><?php } ?> <?php if ( is_month() ) { ?><? bloginfo('name'); ?> | Archive | <?php the_time('F, Y'); ?><?php } ?> <?php if ( is_day() ) { ?><? bloginfo('name'); ?> | Archive | <?php the_time('F j, Y'); ?><?php } ?> <?php if (function_exists('is_tag')) { if ( is_tag() ) { ?><?php single_tag_title("", true); } } ?> | <? bloginfo('name'); ?>
15. Do not forget about breadcrumbs
As an added piece of navigation in your themes, breadcrumbs (in my opinion) should be utilized as much as possible. It is not only good for SEO purposes, but it also allows the visitor to navigate through your site much quicker. There are WordPress plugins for breadcrumbs, but thanks to Cats Who Code, we now know how to add a breadcrumb function into our WordPress themes.
First, add the below codes into your themes functions.php file (customized a bit from the original Cats Who Code post, linked above).
function the_breadcrumb() {
echo '<ul id="crumbs">';
if (!is_home()) {
echo '<li><a href="';
echo get_option('home');
echo '">';
echo 'Home';
echo "</a></li>";
if (is_category() || is_single()) {
echo '<li>';
the_category(' </li><li> ');
if (is_single()) {
echo "</li><li>";
the_title();
echo '</li>';
}
} elseif (is_page()) {
echo '<li>';
echo the_title();
echo '</li>';
}
}
elseif (is_tag()) {single_tag_title();}
elseif (is_day()) {echo"<li>Archive for "; the_time('F jS, Y'); echo'</li>';}
elseif (is_month()) {echo"<li>Archive for "; the_time('F, Y'); echo'</li>';}
elseif (is_year()) {echo"<li>Archive for "; the_time('Y'); echo'</li>';}
elseif (is_author()) {echo"<li>Author Archive"; echo'</li>';}
elseif (isset($_GET['paged']) && !empty($_GET['paged'])) {echo "<li>Blog Archives"; echo'</li>';}
elseif (is_search()) {echo"<li>Search Results"; echo'</li>';}
echo '</ul>';
}
Next, place this piece of code anywhere you want your breadcrumbs to display.
<?php the_breadcrumb(); ?>
Thanks for reading over the article
Thank you for taking the time to read the article. I hope you enjoyed it and learned a thing or two along the way - I know I did. If you liked the post or have anything to add, let us know in the comments.
great post. Thanks for sharing
If you’re working off a solid framework, most of these will be built in.
Awesome tips of what to do and what not to do.
#9 Do not forget the RSS integration, is a really bad idea if as it seems you are going to do it on every page load. It;
a) will do a request per page load for something that doesn’t need to be done each time
b) will wait for the default curl timeout if there is some network issue or problem with the api, this will result in annoyed users & more load as people jab refresh.
c) you may get blocked if your busy and are hammering their API.
Much better would be to take your script and make it output to a static file using cron periodically and load that in to the template. This way end users won’t get hung pages, you can set a longer time out & add error checking and your server won’t get overloaded either.
I enjoyed reading this post. I thought for the most part each idea was pretty spot on.
Great article, learned a couple of things here 🙂 I’ll have to remember this post next times i do a custom theme. BTW for all, great comments that added value to the article itself.
Thing i’ve run across is javascript library which use images (facebox for ex.) : it’s not that easy to make the script behave. I’ve renamed the javascript to .js.php and modified link to referenced images to start with :
/images/myimage.gif
Work great 🙂
Great summary!
I started to read this earlier tonight. Then I went out and had some cocktails..
Good read.. Some truths and some not so important..
I’m aware of all these when building a theme, 😉
I don’t agree with the first point, at least if you’re building the theme for yourself. Using the full path reduces the amount of DB calls and speeds up the load time of your site. Of course, if you’re building this to sell or move around a lot, you have no choice but to use the temp URL call.
Also, most themes, when built specifically for a client, not to sell multiple times on a theme site, don’t need am options panel. This is simply overkill since they’ve already approved the design, and most won’t pay the extra $$ for one. Your theme should work write with little to no setup.
Hey Amber, you’re right, some of these points wouldn’t apply to one-off client themes. For example, if a client does not need/want an options panel, widgets, and other stuff like that. Just putting in an options panel for the fun of it would probably be a waste of your time (and their money too).
For released themes, however, having some sort of options page is almost expected of new WordPress themes. They don’t have to be super advanced, for example, I use simple options pages just to change the color scheme of a theme without having to edit code. This can be especially useful to MU users who don’t have access to change the code themselves.
About the first point, if the theme is only going to be used on only one URL, then the image URL could probably be hardcoded with no issue.
Although for themes used on more than one site (or pretty much any distributed theme) I think hardcoding the images is a definite no-no.
Also part of the point is that I’ve seen themes that call images like
<?php bloginfo('url'); ?>/wp-content/themes/theme-name/images/image.jpg
which would still have a DB call, but would break if the user were to ever change the theme directory.Most of these calls are cached so its only the first call that actually query the database.
I use these functions. don’t really like the get_bloginfo way
There are alot of good functions in the theme.php file.
get_template_directory_uri()
get_stylesheet_directory_uri()
admin_url()
site_url()
plugins_url()
includes_url()
content_url()
home_url() is coming in 3.0.
Options panel is recommended even for one time client though, in case the client wants to change some text which would be hardcoded in the theme otherwise (such as legal notices etc.) .
My clients usually use WordPress as a CMS, so sometimes they want to include pages in the navigation menu. Hardcoding the post IDs for those pages in the navigation menu would be inflexible for the clients in the long run, so again, some sort of configuration panel would be a nice touch.
Good stuff. Thanks for sharing!
Hi Mike,
The hack ‘13. Do not make excessive use of custom fields’ doesn’t always have to work on all off the wordpress-themes. As it didn’t work on the gonzoblog.nl …
But I figured out what the problem was. In some themes this hack just shows the URL of your 1st image and not the actual picture! Change the code for your (home)page to:
<img src="<?php echo catch_that_image() ?>" alt="" class="th" /><!--formatted-->
Now you’ve got a picture on your page! In the gonzoblog my first picture is a divider/spacer for the first paragraph, so I had another problem. The picture I wanted to show is always the second picture, so I had to sort that one out too!
Replace this line in the functions.php, and your second picture will turn up on your homepage:
$first_img = $matches [1] [1]; //Setting to show 2nd picture, first picture: [1] [0]
So, for all you people who also saw just the URL in your home-page, … this is the solution!
LOL ;-P
I think #9 is wrong. The new API call is something like this http://www.wprecipes.com/how-to-display-your-feedburner-count-in-full-text
And a better solution which use a txt file for caching is this one http://www.mdj.us/web-development/php-programming/use-php-curl-to-get-your-google-feedburner-subscriber-count-text-with-result-caching/
Thanks Eugen, for the links. I use the #9 on http://www.guerrillafreelancing.com but haven’t looked into newer versions in a while. Will definitely check it out.
By wrong do you mean it’s outdated for the new API and/or just doesn’t work anymore?
I’ll update the post with those two links, thanks.
The API is outdated.
for #1 it’s best to use bloginfo(‘template_directory’);
http://codex.wordpress.org/Theme_Development#Referencing_Files_From_a_Template
stylesheet_directory should only be used in child themes to reference the child theme directory.
Hey Magnus, thanks for the tip.
Personally I usually use bloginfo(‘template_url’) although I figured they were all pretty interchangeable? Aside from stylesheet_directory which is used primarily for child themes.
Is there any advantage to using one over the other?
Thanks Magnus. I was like Leland, didn’t really look into it too much and thought they were interchangeable, however I haven’t dove too much into child themes, so I am not too ‘in the know’ about those types of things.
Excellent list.
Agreed especially with #12. The theme should revert back to a default option if the enhanced feature that relies on a plugin is not available.