How can I add HTML classes for current taxonomy/term hierarchy into my pages to simplify styles?

Note – I may need to edit this after you give me some feedback.

The trick here is to use either the body_class or post_class filters. Your theme (should) use the body_class function to inject a number of classes into your HTML tag and the complementary post_class function to do the same for whichever tag surrounds your main post content. Their filters let you expand those lists of classes with anything you need.

Since your CSS example has selectors like #content .category-academy-awards .entry-categories a I’m guessing that we are talking about post_class for your question. The two work exactly the same way.

In your functions.php file, start with this:

add_filter('post_class','wpse_235350_custom_body_class');

function wpse_235350_custom_body_class( $classes ) {

    return $classes;

}

Now when WP generates a page and hits the post_class function, it’ll divert to this function, passing the list of classes, then the function returns the list of classes back and WP carries on, turning the array into a string separated by spaces and pushing it into the HTML of your page.

Nothing clever yet, but now we’ll expand the function so that it adds to that list of classes.

I’m assuming that within the loop you want to find out for every post which categories it’s in and then try and find the top level category for each of those and add that top level category to the list of classes. For example, if the post is in category predictions then we’ll go up the tree to find the top level category is academy-awards and so add that as a class to the post.

In my own coding I’d probably condense things more than I’m going to here, and use fewer temporary variables, but that would make for a less clear answer.

First we need to know the categories of the post:

$categories = get_the_category();

This returns an array of category objects. We’ll extract the category IDs from this array:

if( count( $categories ) ) {
// as long as there is at least one category...

    $catlist = array(); // good to make sure it really is empty to start with

    foreach( $categories as $category ) {
        $catlist[] = (int)$category->term_id;
        // WP gets stroppy if you accidentally fail to use integers, so we co-erce the value here.
    }

}

And now we’ll use the really nifty get_ancestors to find all of each category’s ancestors. get_ancestors will pull out a list of all the ancestors of a given object, whether that’s a term or a post or a comment.

$fullcatlist = array();

foreach( $catlist as $category ) {

    $fullcatlist = array_merge( $fullcatlist, get_ancestors( $category, 'category' ) );

}

// now $fullcatlist is a one dimensional array of all the ancestors' IDs, possibly with duplicate values, so...

$fullcatlist = array_unique($fullcatlist);

Now let’s get all the slugs. We get all the category objects and add the slugs to an array, putting the string ‘category-‘ in front of each ready for our classes.

$catsluglist = array();

foreach( $fullcatlist as $category ) {
    $category = get_category( $category );
    $catsluglist[] = 'category-' . $category->slug;
}

And there we have it: A list of all the slugs of all the ancestor categories of the current post.

Putting it all together, we have this:

add_filter('post_class','wpse_235350_custom_body_class');

function wpse_235350_custom_body_class( $classes ) {

    $categories = get_the_category();

    if( count( $categories ) ) {
    // as long as there is at least one category...

        $catlist = array(); // good to make sure it really is empty to start with

        foreach( $categories as $category ) {
            $catlist[] = (int)$category->term_id;
            // WP gets stroppy if you accidentally fail to use integers, so we co-erce the value here.
        }

    }

    $fullcatlist = array();

    foreach( $catlist as $category ) {

        $fullcatlist = array_merge( $fullcatlist, get_ancestors( $category, 'category' ) );

    }

    // now $fullcatlist is a one dimensional array of all the ancestors' IDs, possibly with duplicate values, so...

    $fullcatlist = array_unique($fullcatlist);

    $catsluglist = array();

    foreach( $fullcatlist as $category ) {
        $category = get_category( $category );
        $catsluglist[] = 'category-' . $category->slug;
    }

    return $classes;

}

It’s untested and I’m happy to help debug. Where’s my glass of wine…

Oh – last bit. All of your posts should now have the class category-academy-awards on them, if that is the top level ancestor, as well as any intermediate ancestor categories.

tech