Customizing the WordPress body_class() Function

In this article we'll discuss a short script to add custom classes to the body element of your WordPress page template.

Back in WordPress 2.8, a new template tag was introduced, body_class(). What this template tag does is display dynamic classes for the <body> element of your page. What’s so significant about this function is that this gives us the ability to change the look of essentially every page on a site using CSS only.

How It’s Used

Typically the body_class() tag is placed in the <body> element, which is usually located in the header.php file. It looks like this:

<body <?php body_class(); ?>>

And would return something that looks like this:

<body class="page page-id-2 page-parent page-template page-template-page_about-php logged-in parent-page about">

See the last two classes, “parent-page and “about? Those are custom classes that this article will discuss in a moment. But first, the template tag itself.

The Codex has a great article explaining in greater detail the various classes this tag creates on the <body> element. We won’t go into too much detail in this article, but you can read the Codex article here. Essentially though, the body_class() tag displays classes in the body element depending what page we’re on, whether the user is logged‐in or not, whether the page is a parent Page, etc. A list of conditionals is available in the Codex article explaining the various classes than can be produced.

Additionally the body_class() tag has the ability to accept additional parameters that you can enter yourself when creating a page template. To do so, you would include this in your template file:

<body <?php body_class('my-class-1 my-class-2'); ?>>

Where “my-class-1” and “my-class-2” were your custom classes. That would then produce something like this:

<body class="page page-id-2 page-parent page-template page-template-page_about-php logged-in my-class-1 my-class-2 parent-page about">

Note: when adding parameters to the body element, you separate each with a space and quote the entire string or place them in an array like so:

<body <?php body_class(array('my-class-1', 'my-class-2')); ?>>

While it’s great to have the ability to manually add classes to the body element using these additional parameters, it still requires the developer to manually add classes. And since we developers should always be looking for ways to streamline our work flow and increase our efficiency, a much easier way would be in the form of a function placed in our functions.php and attached to the body_class filter hook. Read on.

The Code

First, the code in its entirety:

<?php
/**
 * Custom class for the WP 'body_class()' function
 * updated: 4/15/10
 */
function dbdb_body_classes($classes) {
    global $wp_query;
    
    // if there is no parent ID and it's not a single post page, category page, or 404 page, give it
    // a class of "parent-page"
    if( $wp_query->post->post_parent < 1  && !is_single() && !is_archive() && !is_404() ) {
        $classes[] = 'parent-page';
    };
    
    // if the page/post has a parent, it's a child, give it a class of its parent name
    if($wp_query->post->post_parent > 0 ) {
        $parent_title = get_the_title($wp_query->post->post_parent);
        $parent_title = preg_replace('#\s#','-', $parent_title);
        $parent_title = strtolower($parent_title);
        $classes[] = 'parent-pagename-'.$parent_title;
    };
    
    // add a class = to the name of post or page
    $classes[] = $wp_query->queried_object->post_name;
    
    return array_unique($classes);
};
add_filter('body_class','dbdb_body_classes');
?>

The Code Explained

Now let’s break the code down and explain each section. The first thing we need to do is declare the $wp_query as “global” so we can use its values in our function.

The first section:

if( $wp_query->post->post_parent < 1  && !is_single() && !is_archive() && !is_404() ) {
    $classes[] = 'parent-page';
};

checks whether or not the Page has a parent ID of “0” and that it’s not a single Post page, an archive page, and a 404 error page (these all have “post_parent” ID’s of “0”, but they’re not parents of any other page). If it does—and it’s not one of those types of pages—then it’s a parent page, so we create a class of “parent-page” and add it to the classes array (which is created by WordPress in the core get_body_class() function.

Yes, the current body_class() function already assigns a class of “page-parent” if the page is a parent Page, but in my testing I discovered it didn’t do it for all pages that should be categorized as a “parent”. For example, using the default body_class() template tag, the Home page of this site returns the following body classes:

<body id="page-home" class="home page page-id-3 page-template page-template-page_home-php logged-in">

As you can see, even though it’s technically a parent page (because it’s not a child of any other page), it’s not given a class of “page-parent” by the default body_class() tag. That’s where this custom filter function comes in. The classes returned for the Home page by the custom filter are:

<body id="page-home" class="home page page-id-3 page-template page-template-page_home-php logged-in parent-page">

The second block in the script checks to see if the current page is a child page, and if so, returns the title of its parent as a class. But first, it replaces all spaces in the title with dashes and then converts the entire title to lowercase. (Note: this pulls the title of the page, not its slug.) Finally, it pre‐pends the title with “parent-pagename-” for readability.

// if the page/post has a parent, it's a child, give it a class of its parent's name
if($wp_query->post->post_parent > 0 ) {
    $parent_title = get_the_title($wp_query->post->post_parent);
    $parent_title = preg_replace('#\s#','-', $parent_title);
    $parent_title = strtolower($parent_title);
    $classes[] = 'parent-pagename-'.$parent_title;
};    

The resulting classes would look like this (taken from “The Author” page of this site):

<body class="page page-id-6 page-child parent-pageid-2 page-template page-template-default logged-in parent-pagename-about the-author">

The default body_class() tag returns a class of “parent-pageid-2”, which is great, but not terribly user‐friendly. Developers and designers tend to know the title, rather than the id of their pages, so this function returns that information (“parent-pagename-about”) to be used if needed.

The third block of the script returns the name of the page as a class:

// add a class equal to the name of post or page
$classes[] = $wp_query->queried_object->post_name;

Again using the “The Author” page of this site, we see the following classes returned:

<body class="page page-id-6 page-child parent-pageid-2 page-template page-template-default logged-in parent-pagename-about the-author">

And finally, the last section of the script returns a unique array of values to avoid duplicate classes from appearing:

return array_unique($classes);

Without doing this you could end up with something like this on your Home page (note the duplicate “home” classes):

<body id="page-home" class="home page page-id-3 page-template page-template-page_home-php logged-in parent-page home">

Next we attach the script to the “body_class” filter hook provided by the Core so it’ll execute when called:

add_filter('body_class','dbdb_body_classes');

Installing The Script

To install, simply copy/paste the code above into your functions.php file and then save the file to your template directory. You can customize it any way you’d like, but be sure to check out the Codex page first to save yourself time.

Notes & Resources

In the next article we’ll discuss how to add a custom id to the body element. Classes are great, but ids give fine‐grain control over your CSS. Until then, here are some external resources I’d recommend if you want to learn more about the body_class() tag:

  • See it in the source.
  • Nathan Rice has a great article about the tag located here.
  • The Codex article on the body_class() tag is located here.

First the Article,
Now the Comments

The individual views expressed within are those of the respective commenter and are not reflective of my own or my clients’. Skip to Comment Form →

What’s wrong with “page-parent”?

@Oren, I’m not understanding the question. There’s nothing wrong with adding a class of “page-parent” if you want to. This shows you how to add a custom class to the body element. If you mean in reference to the class “parent-pagename-NAME-OF-PARENT” added by this function, it’s in keeping with WP’s naming convention. The core file adds a class of “parent-pageid-ID-OF-PARENT“, this just mimics that with a name instead of a number.

Just saying thank you; perfect solution, makes my 5 hours of solution-searching worth while!

@Dave. Thanks! Glad you like it! Hope it works out for you!

Just learning about the body_class function and this has been a great help – your tutorials are some of the best I have read and are always very well presented in a great step by step format … thank you for sharing

Thanks so much for this article, it was exactly what I needed to change background colours for different pages/sections.

@smoo, glad it worked out for you!

Make Yourself Read, Leave a Comment

Comment moderation is enabled. If you don’t see your comment, either it’s your first time commenting, you’re spam, or there was a glitch. If it’s two of the three, no worries, it’ll show up soon. (* Indicates a required field.)

If you want a commenter avatar, check them out here.

Allowed XHTML: <a> <abbr> <blockquote> <em> <strong>
Enclose code in backticks (`); no need to encode, the filter will do that for you.