While this isn’t affecting a lot of people now, it will be in the future. Especially if you use well-supported themes.
Somewhere in version 2.8 or 2.9, WordPress started supporting Theme Updates. In the same way that it supports automatic plugin updates from the plugin repository, a theme developer can now make updates to their theme in the themes repository, and you can upgrade it directly from the WordPress interface.
This is a great thing. Theme developers can fix problems, add features, and have it easy for the users to get those changes right away.
Unfortunately, the theme has historically been the user’s playground. Themes are frequently modified by the user directly. Whether it be for looks or for adding code to be used by plugins or whatever, the theme you’re using is very probably not the theme you downloaded. So upgrading will blow away your changes. Thus, most people are disinclined to upgrade their themes.
The way to avoid this is with a child theme. Child themes derive from another theme, called the parent theme. A child theme, by default, looks exactly like the parent. Then you make your changes to the child, and those changes are used on the site. The parent remains untouched. So, when you upgrade the parent theme, the changes you made don’t go anywhere. They stay right where they are.
So let’s dive right in:
How to Make a Child Theme
First, obviously, install the parent theme. Take note of what directory name it goes into. You can find this on the Theme’s screen, it will tell you what directory each theme is in. The new default theme in 3.0 is “twentyten”. So let’s use that one as our parent.
Now, create a new directory in your /wp-content/themes directory. This is where we’ll put our child theme. Let’s call it “mytheme”.
In the mytheme directory, create a new style.css file. Put this in it:
/*
Theme Name: My Theme
Template: twentyten
*/
@import url('../twentyten/style.css');
Finally, load up WordPress and go activate your new “My Theme” theme. You’ll notice that WordPress tells you both what directory your child theme is in and what directory its parent is located in.
Now you’re running on a child theme. It doesn’t have any changes in it, so it looks exactly like the twentyten theme does, but still, we’re running it.
How to Change Things
Let’s say I wanted to change the color of the post titles to, say, green. A silly change, but it illustrates the point.
Normally, I’d go edit the theme, find wherever the color of the text is defined, and change it or add to it to make the titles change in the way I want. In this case, I do the same thing, but I modify the child theme, and I do it in a way that overrides the specificity of the parent’s CSS code.
To do this, I add this code to mytheme’s style.css file:
#content h2.entry-title a {
color: green;
}
Why that change? Well, I looked at the parent theme and found that “#content .entry-title a” was what it used to define the color of the post title links. To override that, I need to be more specific.
Specificity is a difficult concept for some people, but basically it breaks down to this: When the browser is parsing the CSS, more specific rules take precedence over less specific rules.
In my case I needed to be more specific than “#content .entry-title a“. By adding the h2 to the .entry-title rule, I achieve that because h2.entry-title only will affect h2’s with the entry-title class, while just .entry-title can affect any tag on the page with that class.
The fact that only the h2’s on my page have .entry-title is irrelevant. The HTML doesn’t actually matter in regards to specificity. A rule is more specific based on what it can affect, not on what it actually affects.
So by making my rule more specific, I can override the color of those title’s in my own CSS file separately, and without changing anything about the parent theme.
Overriding Templates
Child themes are not limited to overriding only styling, although in many cases that may be the only customization you need. Best to stick with the rule of the minimum; try to make the most minimal change you can make to accomplish what you want to accomplish. But if you do want to change the way some of the templates work, you can do that too.
All you have to do is to copy the specific template file you want to alter from the parent theme into the child theme’s directory, then make your changes. The way WordPress works is when it looks for some template file, it looks in the child theme first, then it goes to the parent theme if the file it wants isn’t there.
Note that you’re not limited to overriding existing files in the parent. The entire Template Hierarchy applies to child themes too, so if you want to define a category.php file for Category Templates, and the parent theme doesn’t have that file, then you can create a new one in your child and it will be used. You will probably still want to start out with some existing template from the parent though, so look at the Template Hierarchy to see which template the parent is using for your case. The index.php is the usual suspect in these cases, so you can probably just copy that to the child theme and rename it to the template file you want it to be.
Overriding Functions
One exception to the overriding mechanism of child themes has to do with the functions.php file. In a child theme situation, both functions.php files from both themes are loaded. This is necessary because elements of your parent theme might require pieces of the functions.php file to be loaded. This can make overriding functions in the parent theme tricky unless it’s written to allow you to do just that.
The key to this is that the functions.php file of the child theme is loaded first. So if the parent theme is written in a manner WordPress calls “pluggable“, then you can override those functions.
In the twentyten theme’s functions.php file, several of the functions are defined like this:
if ( ! function_exists( 'twentyten_admin_header_style' ) ) :
function twentyten_admin_header_style() {
...
}
endif;
That is a pluggable function. Basically, before it defines the function, it checks to see if the function is already defined. If the parent theme uses this mechanism, then a child theme can override this function by simply defining a function of the same name first. So all you have to do to change it is to copy the function into your child’s functions.php file and make your changes. When the parent theme loads, it will see that you already defined the function and continue on.
Another way to override things is through the normal WordPress action and filter hook mechanisms. If a theme’s functions.php file uses those, then you can simply add your own hooked functions with different names. However, because the child’s functions.php file loads first, it can’t actually unhook things defined by the parent theme.
The way to get around this is to use the after_setup_theme action hook. This action is called immediately after both functions.php files are loaded.
For example, if I look at the twentyten theme, I’ll find this:
function twentyten_excerpt_length( $length ) {
return 40;
}
add_filter( 'excerpt_length', 'twentyten_excerpt_length' );
I don’t want that, I want my excerpts to be 55 words instead. So I add this to my functions.php file:
function my_excerpt_length( $length ) {
return 55;
}
add_filter( 'excerpt_length', 'my_excerpt_length' );
Whoops! It doesn’t work. Why not? Because I didn’t remove twentyten’s hook, and its filter is overriding mine. So I have to add this too:
function my_undo_hooks( $length ) {
remove_filter( 'excerpt_length', 'twentyten_excerpt_length' );
}
add_action( 'after_setup_theme', 'my_undo_hooks' );
And then it works. I’ve added my filter, and removed the one in twentyten. Voila.
Programmer Note
In a WordPress theme you’ll often find references to “stylesheet_uri” and “stylesheet_dir”. You’ll also find references to “template_uri” and “template_dir”. Normally, these are the same thing. In a child theme case, they’re not. Stylesheet refers to the child theme. Template refers to the parent theme. This is an important distinction that you’ll want to make when creating your theme. You should probably use stylesheet in most cases, except for when you need to specifically refer to the parent (for image URL creation and such).
Conclusion
Child themes are a very good way to survive theme upgrades, and if you’re using a well supported theme, these are likely to become more common. It’s still perfectly safe to modify your theme directly (except for twentyten! Normal WP upgrades overwrite twentyten), but it’s always a good idea to keep your customizations separate. They’re a lot easier to manage that way.
WordPress 3.0 Theme Tip: The Comment Form
WordPress 3.0 has something very handy that I want theme authors to start implementing as soon as possible.
To show exactly why it’s so useful, I modified my own theme to start using it.
Demonstration
So, here’s a big hunk of code I pulled out of my current theme’s comments.php. This hunk of code has only one purpose: To display the form area where people can leave a comment:
Nasty, eh? It’s a mess of if/else statements. It handles cases where the user is logged in or not, where the comments are open or closed, whether registration is required, etc. It’s confusing, difficult to modify, poor for CSS referencing…
Here’s what I replaced all that code with:
Now then, that’s much better, isn’t it?
The comment_form function is new to 3.0. Basically, it standardizes the comments form. It makes it wonderful for us plugin authors, since now we can easily modify the comments form with various hooks and things. I’ve already modified Simple Facebook Connect and Simple Twitter Connect to support this new approach; if you’re using a theme with this, then the user won’t have to modify it to have their buttons appear on the comments form.
Customizing
Since theme authors love to customize things, the comments form is also extremely customizable. Doing it, however, can be slightly confusing.
Inside the comments_form function, we find some useful hooks to let us change things around.
The first hook is comment_form_default_fields. This lets us modify the three main fields: author, email, and website. It’s a filter, so we can change things as they pass through it. The fields are stored in an array which contains the html that is output. So it looks sorta like this:
I truncated it for simplicity. But what this means is that code like this can modify the fields:
That sort of thing lets us add a new input field, or modify the existing ones, etc…
But fields aren’t the only thing we can change. There’s a comment_form_defaults filter too. It gets a lot of the surrounding text of the comments form. The defaults look sorta like this:
All the various pieces of html that are displayed as part of the comment form section are defined here. So those can be modified as you see fit. However, unlike the fields, adding new bits here won’t help us at all. The fields get looped through for displaying them, these are just settings that get used at various times.
But filters are not the only way to modify these. The comment_form function actually can take an array of arguments as the first parameter, and those arguments will modify the form. So if we wanted a simple change, like to change the wording of “Leave a Reply”, then we could do this:
This gives us a simple and easy way to make changes without all the trouble of filters. Nevertheless, those filters can be very useful for more complex operations.
But wait, there’s more!
As the comments form is being created, there’s a ton of action hooks being called, at every stage. So if you want to insert something into the form itself, there’s easy ways to do it.
A quick list of the action hooks. Most of them are self-explanatory.
CSS and other extras
Let’s not forget styling. All parts of the comments form have nice classes and id’s and such. Take a look at the resulting HTML source and you’ll find all the styling capabilities you like. Also, everything is properly semantic, using label tags and aria-required and so forth. All the text is run through the translation system for core translations.
So theme authors should start modifying their themes to use this instead of the existing big-ugly-comment-form code. Your users will thank you for it. Plugin authors will thank you for it. And really, it’s about time we made WordPress themes more about design and less about the nuts and bolts of the programming, no?
Category: Code, WordPress | 243 Comments