WordPress’s body_class() function already outputs a useful set of CSS classes on the body element, things like single, page, home, logged-in, and post ID classes. But it doesn’t always give you the granular targeting you need for template-specific styling. Knowing a page uses a specific template file, belongs to a specific category, or is a specific custom post type often requires adding those classes yourself.
The body_class filter makes this straightforward, append whatever classes are useful to your CSS workflow and they’ll be available on every relevant page without any JavaScript or inline styles.
The Code
Add this to your functions.php or a site-specific plugin. The filter receives the current array of body classes and returns the modified array. array_unique() at the end prevents duplicate classes if any of the generated values happen to match an existing class.
Post Type Classes
The first block adds a post-type-{slug} class on all singular views. WordPress already adds a class like single-post or single-{post-type} to the body, but the format is inconsistent between post types. Adding a consistently formatted post-type- prefixed class gives you a predictable CSS hook regardless of post type, for example post-type-nahnu_snippet or post-type-portfolio.
Page Template Classes
The page template block uses get_page_template_slug() to retrieve the filename of the template assigned to the current page, for example templates/full-width.php. basename() strips the directory path and file extension, leaving just the slug. sanitize_html_class() ensures the result is a valid CSS class string. Pages using the default template get template-default.
This class makes it easy to write CSS that only applies to pages using a specific template, without needing to use the page ID or a custom field as the targeting hook.
Category Classes
The category block adds a category-{slug} class for every category the current post belongs to. WordPress already adds category classes in some theme configurations, but the implementation varies. Adding them explicitly through this filter ensures they’re always present and consistently formatted for CSS targeting, useful for applying different accent colours or layout adjustments per category.
Extending the Filter
The same pattern extends to any conditional you need. Custom taxonomies, archive types, user roles, time of day, A/B test variants, anything that can be evaluated server-side can become a body class. The class becomes a CSS hook that lets you apply styles from your stylesheet without touching templates or adding inline style attributes.
add_filter( 'body_class', function( $classes ) {
// Add a class for each custom post type
if ( is_singular() ) {
$classes[] = 'post-type-' . get_post_type();
}
// Add a class for the active page template
if ( is_page() ) {
$template = get_page_template_slug();
if ( $template ) {
$slug = basename( $template, '.php' );
$classes[] = 'template-' . sanitize_html_class( $slug );
} else {
$classes[] = 'template-default';
}
}
// Add a class for each taxonomy term on singular posts
if ( is_singular( 'post' ) ) {
$terms = get_the_terms( get_the_ID(), 'category' );
if ( $terms && ! is_wp_error( $terms ) ) {
foreach ( $terms as $term ) {
$classes[] = 'category-' . sanitize_html_class( $term->slug );
}
}
}
// Add a class on the front page regardless of whether it's static or the blog
if ( is_front_page() ) {
$classes[] = 'is-front-page';
}
return array_unique( $classes );
} );
