'

Ultimate WordPress body_class function

I wasn’t happy with the default body_class() function in WordPress. I wanted to assign more classes to the body element in order to target various sections or specific pages across the website, so that to style them appropriately.

Filtering the body_class() function is a common practice and I found several resources to help me in the task. I started playing around and soon I noticed that I was scrambling the post_class() function and its effectiveness, overlapping classes among body element and the post container.

Duplicated classes

In fact the post_class() prints the categories the post is assigned to. For instance, assuming we’re opening the archive page for the category Rejser, we will have something similar to this.

<body class="archive category category-rejser category-13">
<!-- few lines after... -->
<article id="post-139" class="post-139 post type-post status-publish format-standard hentry category-rejser post-body">

So, if you don’t take this in count when assigning additional classes to the body, you could observe that the class category-rejser has been assigned to both the body element and the post container. I would rather have a simpler structure so that to precisely target elements in a page.

Elements of different nature should not share the same classes. If they do, then you need to specify which element you’re willing to style, and this complicates your stylesheet.

body.category-rejser { /* styling */ }
div.category-rejser { /* styling */ }

Sure you can live with it. But I do prefer simplicity.

The Ultimate body_class filter

After experimenting a little bit I ended up with a solution I’m quite happy with. Here we go.

<?php
if ( ! function_exists('my_body_class')) {
add_filter('body_class','my_body_class');
function my_body_class($classes) {
	global $wp_query, $post;
	if ( is_front_page()) { $classes[] = 'front-page'; }
	if ( is_page()) { $classes[] = 'page-'.$wp_query->query_vars['pagename']; }
	if ( is_singular()) { $classes[] = 'slug-'.$post->post_name; }
	if ( is_singular()) { $classes[] = 'post-type-'.$post->post_type; }
	if ( !is_404() && get_the_category( $post->ID)) {
		foreach (( get_the_category($post->ID)) as $category)
		$classes[] = 'body-category-'.$category->category_nicename; // pay attention, it might be duplicated in the post
	}
	return $classes;
}} ?>

I still add a specific class to the body element when I’m visiting a category page but I make sure that it does not overlap with the categories eventually assigned to posts. If you’re not happy with the solution, change the line.

$classes[] = 'body-category-'.$category->category_nicename;

In something that better works for you.

How to use it?

The easiest way to empower the body_class() function is to copy and past the code above directly into the functions.php file of your theme. Assuming the theme does not have already a similar feature.

The files of a theme are usually located in the folder

wp-content/themes/theme-name/

And the functions.php file is placed the root of the theme.

If the file isn’t present, you have to create it. A plain and simple text editor will do a honest job.

Pay attention to respect the PHP syntax, so that everything into the file is correctly encased within <?php and ?>.

A quick note on a 404 error

Lately I slightly modified one of the last line in the final function.

if ( !is_404() && get_the_category( $post->ID)) { /* ... */

At first the conditional verifies that the page isn’t a 404 code. In fact, I found out that in case the user tries to open a page which is not available (and gets a 404 error), WordPress notifies with an error.

To enable WP_DEBUG (in wp-config.php).

define('WP_DEBUG', true); 
/* if WP_DEBUG is "false" problems are still there just stay silent */

Now that WP_DEBUG is set as true you might get this error incurring in a 404 page.

Notice: Trying to get property of non-object in your-domain/wp-includes/category-template.php on line 1082 class="error404 logged-in admin-bar">

So, if we’re on a 404 page, we need to skip get_the_category() entirely.

Conclusion

What is your approach to styling starting from the body, so far? Do you have a better code for empowering the body_class()? Would you like to let me know your opinion?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>