6 Things I Learned Designing a Custom WordPress Theme

My free time for the past two weeks has been spent building the new WordPress theme that you see here. Now that I’ve finished the project, I’m starting to reflect on my experience, and while I found a ton of great resources, it wasn’t entirely positive.

Frequently, there was information that I wasn’t able to find – either because I didn’t know where to look or because the information didn’t exist. My only path forward was to crawl through the WP-Includes folder to gather how things work, step-by-step. Coming from someone who used to run API usability tests, I can say this far from the ideal developer experience.

Well, I can’t do anything about the WordPress framework. But hopefully some of the things I learned will help other people, so I’ve captured them here.

1. Having a starting point helps immensely.
I remembered seeing something on Digg a while back about blank WordPress themes, and after a quick search I found the folks over at Tomorrows Laundry, offering four blank wordpress themes ready for you to customize. I chose the 2-Column Right Menu Fixed version. Can you see the resemblance?

The blank template I started with - a simple right-column design

What’s brilliant about these themes is that all your effort works toward building your theme – no un-building of someone else’s theme required. My ability to modify my last theme was extremely limited because the code was setup very poorly. When you start with a structured blank slate, you’re productive from day one.

2. Include a reset.css file.
I first stumbled upon the notion of reseting CSS in Smashing Magazine and the world has been a beautiful (and browser-consistent) place ever since. The Yahoo! UI group has amazing resources on reseting CSS, including the code for a reset.css file.

Once I incorporated the reset.css file, I only had one browser consistency issue between IE7, Firefox & Safari. Incidentally, the problem was fixed by adding one line to the reset.css file under the li style:

list-style-position: outside;

3. You probably don’t need to change anything in the WP-Include files.
I can hear all the WordPress architects scoffing at me now. “Of course you don’t,” they are saying. Unfortunately, when you can’t find documentation on your issues, you resort to drastic measures.

Practically, let me tell you what I was after. My header and stylesheets vary from category to category. In order to accomplish that design, I needed to know the post’s category (or more accurately, the category used in the database query). Tricky bit: my header is (correctly) outside The Loop, and all documentation about category-specific styles points to changes inside The Loop.

I started to change the general-template.php file, until, after crawling through the query.php file (best Saturday night EVAR) and cross-referencing my theme files, I started looking at the get_query_var( ) method. Tricky bit #2: The method isn’t in the WordPress codex, so understanding how it works is trial and error at best.

If you’re curious, here’s what I ended up with when all was said and done. This line of code sits in a PHP block at the top of my header file, and gives me direct access to my category slug, enabling category-specific design throughout the page:

$catSlug = get_query_var(‘category_name’);

4. WordPress sidebar widgets aren’t flexible enough.
My sidebar is old school. And on some levels, that makes me sad. I was totally digging the power behind the Subscribe2 widget. Unfortunately, it was lacking in flexibility.

First of all, my blog is highly driven by its categories, so I need my widgets to be category specific. Having unique sidebars for each category got me halfway there, but without category-specific widgets, duplicating sidebars is pointless. I encountered maybe three widgets that allowed you to narrow the view by category.

Secondly, even if I managed to configure all the widgets to understand what category they lived in, I can only use each widget once!!! That’s a pretty poor design decision on someone’s part. Kudoz to the authors of JAW Duplicate Widgets for trying to solve this problem, but their solution falls short. Their plugin allows you to duplicate widgets as configured, meaning I can’t have uniquely configured widgets on different sidebars.

It’s unfair for me to complain since I’m not contributing to the widget pool (though I intend for that to change), but fair or not, this is a legitimate problem I ran into, and I doubt I’m alone. Be aware that if you want to do non-standard stuff with your sidebar(s), you might end up flying solo.

5. Searching by category is insanely easy.
Restricting blog searches to a particular category was something that stumped me for a long time. Tons of people want it. None of the common widgets offer the functionality without being completely bloated and over-engineered. And finding help on this topic proved to be difficult.

Then I found Lisa over at E.Webscapes, who talks about work she did for a client that required some intense category work. She doesn’t expand much on searching by category, but after reading what she had to say, I figured out how easy this really was.

To show you how this works, check out the code for the standard text box in my template’s searchform.php page (this is pretty standard):

<input type=”text” class=”textBox”
    value=”<?php echo wp_specialchars($s, 1); ?>”
    name=”s” id=”s” />

The part that says name=”s” means that the value in that text box will be your search parameter. That begs the question: Are there other parameters to send from the search form?

The answer is yes. In my case, I wanted the category name, so I just added name=”category_name” to a form field, like so (note that this is inside a PHP block):

echo ‘<input type=”hidden” name=”category_name”
    id=”category_name” value=”‘ . $catSlug . ‘”>’

I used a hidden field, but you can use any standard form field for this. Wasn’t that easy? If you want more fine-grained search filtering, this codex page on query parameters gives you a lot of items that should work exactly the same as category_name did. However, I make no promises since I haven’t tried it myself.

6. WordPress export is good but not great.
For better or worse, I literally started from scratch with this blog. New domain, new directory on my site, new categories, new permalink structure, new database. WordPress’s exporting feature made moving the content over very easy, but all my post-to-post links and images were still pointing to the old domain. All told, I probably spent 5 hours or so pointing everything to the new domain.

It seems to me like it wouldn’t be terribly difficult to note the TEMPLATEPATH parameter along with the export, and when you do an import, compare the new TEMPLATEPATH to the old one, and if they vary, do a substitution wherever it appears in blog posts. Maybe it’s not feasible (I never claimed to be a developer), but it sure would have saved me a ton of time.

All things considered, it went pretty well.
Overall, I’m elated that I was able to produce this theme in such a short amount of time. The first two points probably saved me many hours of frustration. Hopefully the latter four points will save my readers a few more hours of frustration. Remember to pay it forward.

Be Sociable, Share!

The conversation continues...

  1. On April 22nd, 2008 at 2:12 pm, gautch said:

    I’m using one of the Tomorrows-Laundry blank theme, but i can’t seem to get images to show up.

    Did you run into this?

  2. On April 22nd, 2008 at 2:16 pm, zsz said:

    Not really. I occasionally have syntax issues with images – especially when I first started using background images – but nothing that was related to the theme.

    What I’d advise is to make sure that your image directory is inside your theme directory, not in the root directory. For all relative file references in your theme files, it starts in your theme directory.

  3. On November 23rd, 2008 at 5:02 pm, Adrian said:

    Point number 3 saved me from a mental breakdown after staring at the codex for HOURS, mumbling “surely there’s a way of getting the category slug outside of the loop” over and over into my keyboard. Thanks!

What do you think?