Style Posts by Taxonomy

We heard this question many times and it’s not as simple as it sounds, so we’re dedicating a whole blog post to the solution. Today we’ll talk about child themes, taxonomy (categories, tags and custom taxonomy), the post_class function, it’s filter friend and their correct usage in WordPress themes.

As simple as it sounds, adding the appropriate CSS rules to your theme stylesheet doesn’t always work unless you’re using default themes or very well written ones. Then again, even if it does, you might see it broken during the next update to the theme you’re using, which brings us to child themes.

Why Child Themes?

Child themes in WordPress is a theme that inherits everything from it’s parent theme while having the ability to append, extend and override the functionality, templates and styles of the parent theme. Parent themes get updated, child themes usually don’t, so you won’t loose any changes during updates, especially if you created the child theme yourself.

As the codex article explains, it’s very easy to create a child theme and the only thing you need is a style.css file which will be used instead of the parent’s theme. Take note that if your goal is not to override the parent theme’s styles completely, your stylesheet should include an @import rule that includes the parent theme’s CSS file before your extending rules. Also note that not all themes are suitable to be parent themes, but Twenty Eleven certainly is.

A Word About Taxonomy

I’m pretty sure you’re aware that Taxonomy in WordPress is a way to group things and WordPress currently ships with two default ones — tags and categories. Yes, post formats (since 3.1) are based on taxonomy too but that’s a little bit of a different story. You can easily add your own taxonomy with the register_taxonomy function which has been available since version 2.3.

So back to our question, how do you style posts based on tags, categories or custom taxonomies in WordPress. With regards to tags and categories, most of the work has been done for you and we’ll talk about “what work” later when working with custom taxonomies. Let’s now take a look at the function that makes styling possible.

The post_class Function

This is pretty important when it comes styling posts. The post_class outputs the class attribute to use with WordPress posts. Classes contain information like the post ID, type, format, status, categories and tags, for example:

post-358 post type-post status-publish format-standard hentry category-cat-a category-highlights-2 tag-chattels tag-highlights tag-privation

And as seen from Twenty Eleven, here’s how the post_class function is used within the loop:

<article <?php post_class(); ?>>

Note that class= isn’t required since post_class will output that as well and do make sure that the function is used inside the loop, otherwise it just won’t work. Also keep in mind that post_class should be used on an element that’s parent to all the rest of the stuff related to the post, like the title, content or excerpt, author, tags, etc.

Now that that’s done you should be able to use Chrome’s inspector or Firebug to see what classes were generated for each of your posts. Here’s what we found out form Twenty Eleven:

Chrome Inspector on Twenty Eleven

Now with that sorted out, you can easily style your posts based on categories, tags, types and formats:

.post.category-cat-a { background: red; }
.post.tag-privation { background: yellow; }
.post.type-post { background: green; }
.post.format-standard { background: orange; }

Of course these styles don’t make any sense together, but you should get the basic idea. Keep in mind that the extra rules should go into your child theme’s stylesheet and not the parent, otherwise they will be overwritten by the next update.

What’s more interesting is the post_class filter, which you can hook to and extend with other class names. A good usage scenario is custom taxonomies, which we’ll discuss next.

Custom Taxonomies and post_class Filter

Custom taxonomies is a way to create your own grouping for posts and other post types and the best example we can provide here is a new taxonomy called Person. Let’s go ahead and create our new taxonomy in your child theme’s functions.php file, like this:

function my_register_taxonomy() {
    register_taxonomy( 'person', array( 'post' ), array(
        'hierarchical' => false,
        'show_ui' => true,
        'query_var' => true,
        'rewrite' => array( 'slug' => 'people' ),
        'labels' => array(
            'name' => __( 'People' ),
            'singular_name' => __( 'Person' ),
            'search_items' => __( 'Search People' ),
            'popular_items' => __( 'Popular People' ),
            'all_items' => __( 'All People' ),
            'edit_item' => __( 'Edit Person' ),
            'update_item' => __( 'Update Person' ),
            'add_new_item' => __( 'Add Person' ),
            'new_item_name' => __( 'New Person' ),
            'menu_name' => __( 'People' )
        )
    ) );
}
add_action( 'init', 'my_register_taxonomy' );

This will bring a new meta box to the edit post interface, very similar to tags (since people are not hierarchical) so you can attach people to your posts now:

Taxonomy People Metabox

That’s only half of the job. Suppose you want posts with Michael Jackson have a red background and posts with John Lennon a blue one. How would we do that? First thing’s first, we can use the Chrome inspector or Firebug to see if extra classes has been added to our post markup, but unfortunately, WordPress doesn’t do that for us, so we’ll have to do it ourselves, and that’s where the post_class filter comes in. Add this to your child theme’s functions file:

function my_post_class( $classes ) {
    global $post;
    $terms = wp_get_object_terms( $post->ID, 'person' );
    foreach ( $terms as $person ) {
        $classes[] = 'person-' . $person->slug;
    }
    return $classes;
}
add_filter( 'post_class', 'my_post_class' );

The code is quite simple here, we’re using the global $post object and the wp_get_object_terms function to grab the terms under the person taxonomy related to our post. You can use print_r to inspect the $terms array and the snippet above shows how to add each person’s slug to the classes array which is finally returned.

After you’ve implemented this you can use Firebug again to find the new class names in the markup, easily accessible in your stylesheet, like this:

.post.person-michael-jackson { background: red; }
.post.person-john-lennon { background blue; }

One thing to watch out for here is the fallback rules, like what happens if a person hasn’t been attached to a post at all, or if one has been but rules for that are not provided in your stylesheet? You don’t want to end up with white text on a white background or something, right? So don’t forget to test things out before you go public ;)

Conclusion

Hopefully we’ve shown the power of the post_class function together with it’s filter. You can use it to add more classes other than taxonomy, even stuff like content length, post thumbnail presence, number of tags or categories, the publish date and even the number of comments. Also take a look at a similar function/filter pair called body_class.

Thank you for reading and hope you enjoyed it. Let us know if you have any questions or thoughts using the comments section below and thanks for staying tuned!