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?
