How to Add Custom Body Classes in WordPress
The <body> class attribute is one of the most powerful (and often underused) tools in WordPress theming. By adding custom body classes, you can target specific pages, post types, templates, or conditions with clean, maintainable CSS and JavaScript — without relying on inline styles or messy selectors.
This article explains how to add custom body classes properly in WordPress, with practical examples you can use in real projects.
What Are Body Classes?
WordPress automatically outputs contextual classes on the <body> tag using body_class().
Example output:
<body class="home blog logged-in admin-bar">
These classes reflect the current page type, login state, template, and more — making them ideal hooks for styling and behavior.
Always Use body_class() in Your Theme
First, make sure your theme outputs body classes correctly.
<body <?php body_class(); ?>>
If body_class() is missing from header.php, none of the techniques below will work.
How to Add Custom Body Classes (The Right Way)
Use the body_class filter. This is safe, future-proof, and compatible with plugins.
add_filter( 'body_class', function( $classes ) {
$classes[] = 'my-custom-class';
return $classes;
} );
This adds my-custom-class to every page.
Add Body Classes Conditionally
In most cases, you want classes only on specific pages or conditions.
Add a class only on the homepage
add_filter( 'body_class', function( $classes ) {
if ( is_front_page() ) {
$classes[] = 'is-front-page';
}
return $classes;
} );
Add a class only on single posts
add_filter( 'body_class', function( $classes ) {
if ( is_single() ) {
$classes[] = 'is-single-post';
}
return $classes;
} );
Add a class for a specific page slug
add_filter( 'body_class', function( $classes ) {
if ( is_page( 'contact' ) ) {
$classes[] = 'page-contact';
}
return $classes;
} );
This is useful for landing pages and one-off designs.
Add Body Classes for Custom Post Types
Class for all posts of a CPT
add_filter( 'body_class', function( $classes ) {
if ( is_singular( 'product' ) ) {
$classes[] = 'single-product-page';
}
return $classes;
} );
Different class per CPT archive
add_filter( 'body_class', function( $classes ) {
if ( is_post_type_archive( 'event' ) ) {
$classes[] = 'archive-event';
}
return $classes;
} );
Add Body Classes Based on Page Template
WordPress already adds a template-based class, but you can customize or simplify it.
add_filter( 'body_class', function( $classes ) {
if ( is_page_template( 'templates/landing.php' ) ) {
$classes[] = 'tpl-landing';
}
return $classes;
} );
Add Body Classes Based on User State
Logged-in vs logged-out
add_filter( 'body_class', function( $classes ) {
if ( is_user_logged_in() ) {
$classes[] = 'user-logged-in';
} else {
$classes[] = 'user-logged-out';
}
return $classes;
} );
This is useful for UI differences without PHP conditionals in templates.
User role–based body class
add_filter( 'body_class', function( $classes ) {
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
if ( ! empty( $user->roles ) ) {
$classes[] = 'role-' . esc_attr( $user->roles[0] );
}
}
return $classes;
} );
Example output:
role-administrator
Add Body Classes Based on Taxonomy
Single post with a specific category
add_filter( 'body_class', function( $classes ) {
if ( is_single() && has_category( 'news' ) ) {
$classes[] = 'cat-news';
}
return $classes;
} );
Custom taxonomy term
add_filter( 'body_class', function( $classes ) {
if ( is_tax( 'genre', 'rock' ) ) {
$classes[] = 'genre-rock';
}
return $classes;
} );
Sanitizing Dynamic Body Classes
If you generate classes dynamically, always sanitize them.
add_filter( 'body_class', function( $classes ) {
if ( is_page() ) {
$slug = get_post_field( 'post_name', get_queried_object_id() );
if ( $slug ) {
$classes[] = 'page-' . sanitize_html_class( $slug );
}
}
return $classes;
} );
Never trust raw values for class names.
Where to Put This Code
- Best: Code Snippets plugin (easy to manage and disable)
- Also OK: Child theme
functions.php - Best for many rules: Small custom plugin
Common Mistakes to Avoid
- Hardcoding classes directly in
header.php - Forgetting to return
$classesin the filter - Adding too many highly specific classes unnecessarily
- Using unsanitized dynamic values
Why Body Classes Matter for Clean CSS
Instead of writing CSS like this:
.page-id-42 .site-main .content .title {}
You can write:
.page-contact .title {}
This improves readability, maintainability, and long-term scalability.
Conclusion
Custom body classes give you a clean separation between logic and presentation. By using the body_class filter correctly, you gain precise control over styling and behavior without cluttering templates or writing fragile selectors.
Key takeaway:
Add body classes via filters, keep them meaningful, and let CSS and JS do the rest.
This small technique makes a big difference in professional WordPress theme development.
🎨 Want to learn more? Visit our WordPress Customization Hub for tips and advanced techniques.