• Skip to main content
  • Skip to primary sidebar
  • Skip to footer

nSiteful Web Builders

Building a Better Web - One Site at a Time.

  • Home
  • About
    • Testimonials
    • Resources
    • Partner With Me
    • Frequently Asked Questions
  • Web Sites
  • Online Marketing
  • WordPress Support
    • Customized WordPress Training
    • 60-for-60 Sessions
  • Web Applications
  • Blog
    • At-A-Glance
    • Blog Articles Grouped by Category
    • Case Studies
    • General
    • Portfolio
    • Reviews
    • Snippets
    • Techniques
    • Projects
  • Contact
    • Purchase Retainer Consulting Hours
    • About Retainer Consulting Hours
    • Book a Meeting with Jeff
    • Tell Me About Your Web Project
    • nSiteful Newsletter Archives
    • nSiteful Rewards
Target Body Class

By Jeff - 5/15/2024
Cats: Snippets · Tags: CSS, WordPress

snippets

Adding Taxonomies to the WordPress Body Class

On this page...

Toggle
  • Use Case for Adding Taxonomies to the WordPress Body Class
  • Categories/Tags to the Rescue
    • PHP Script to add post category to body class list:
    • CSS targeting body class:
  • Does this Body Class solution work for Pages?
    • PHP Script to enable categories and tags for Pages:
  • What about Custom Post Types?
    • PHP Script to enable tags for Custom Post Types:
  • Remember Post Formats?
    • Which is better?
  • Comments Welcome

Last updated June 22nd, 2024 at 06:34 pm

Use Case for Adding Taxonomies to the WordPress Body Class

Sometimes it’s desirable to render WordPress posts or pages distinctively based on the categories or tags assigned to them. (Spoiler alert: leverage the body class property.)

For example, suppose your WordPress blog consists of articles that are categorized as either Documentation or Ramblings. The Documentation category is for formal, structured articles that explain processes and procedures. The Ramblings category is for informal articles through which you share — well, ramblings — that cover lots of different topics.

Further suppose that you want to display your Documentation posts in a formal way and your Ramblings posts in an informal way.

You’ve decided that the way to do this is to use a formal serif font for Documentation and an informal handwriting font — as well as a background image that looks like lined notebook paper — for Ramblings.

Ramblings example
Ramblings Styling Example

How would you accomplish this?

Categories/Tags to the Rescue

One way is to add category and tag classes to the body element and to write rules with appropriate selectors.

“But doesn’t WordPress already do this?” you ask.

Sort of.

While many WordPress themes automatically add the category and tag identifiers to the article element, they do not (by default) add such identifiers to the body element. The reason this matters is that some of the HTML elements you want to render differently (based on the post’s categories or tags) are outside of the article element. (The body element — which you’d most likely want to target for the lined notebook paper background image — is such an element.)

So, the trick is simply to add category and tag identifiers to the body element. And this is pretty easy to do for blog posts, since categories and post_tags are enabled for blog posts by default.

Here’s how:

PHP Script to add post category to body class list:

function nwb_add_category_to_single_action() {
	add_filter('body_class','nwb_add_category_to_single');
	function nwb_add_category_to_single($classes) {
		if (is_single() || is_page() ) {
			global $post;
			foreach((get_the_category($post->ID)) as $category) {
				// Add category slug to the $classes array
				$classes[] = $category->category_nicename;
			}
		}
		// Return the $classes array
		return $classes;
	}
}
add_action('after_setup_theme', 'nwb_add_category_to_single_action');

Now, every post categoried as Documentation will have a body class of documentation, and every post categorized as Ramblings will have a body class of ramblings.

All that’s left to do is add CSS rules that create your desired effects. Examples:

CSS targeting body class:

body.ramblings {
	background-image: url(/images/lined-paper.png);
	background-repeat: repeat-y;
	font-family: "Comic Sans" cursive;
}
body.documentation {
	font-family: "Times New Roman", Times, Georgia, serif;
}

Does this Body Class solution work for Pages?

Actually, the script above does address pages (see line 4, where the condition says, “If this is a single post or a page, then…”).

However, WordPress does not (for whatever reason) enable categories or tags for pages by default. The good news is that you can do that easily. Add these lines of code, using the WordPress register_taxonomy_for_object_type function, to your child theme’s functions.php (or, as I prefer, to a file in your mu-plugins folder):

PHP Script to enable categories and tags for Pages:

function nwb_add_taxonomies_to_pages() {
	register_taxonomy_for_object_type( 'post_tag', 'page' );
	register_taxonomy_for_object_type( 'category', 'page' );
}
add_action( 'init', 'nwb_add_taxonomies_to_pages' );

What about Custom Post Types?

The process is very similar for custom post types, with a few minor exceptions. This example uses the MembersPress Lesson post type (mpcs-lesson and is documented more fully here.

First, you need to make sure that the mpcs-lesson post type supports tags. And since I’m creating a new taxonomy for Lessons (i.e., I don’t want to use the categories and post_tags that “come with” WordPress posts), I need to do a little more work.

PHP Script to enable tags for Custom Post Types:

Register the custom taxonomy (in this case, lesson_tags) like so:

add_action( 'init', 'fto_tax_lesson_tags', 0 );
function fto_tax_lesson_tags() {

	$labels = array(
		'name'                       => 'Lesson Tags',
		'singular_name'              => 'Lesson Tag',
		'menu_name'                  => 'Lesson Tags',
		'all_items'                  => 'All Lesson Tags',
		'parent_item'                => 'Parent Item',
		'parent_item_colon'          => 'Parent Item:',
		'new_item_name'              => 'New Lesson Tag',
		'add_new_item'               => 'Add New Lesson Tag',
		'edit_item'                  => 'Edit Lesson Tag',
		'update_item'                => 'Update Lesson Tag',
		'view_item'                  => 'View Lesson Tag',
		'separate_items_with_commas' => 'Separate items with commas',
		'add_or_remove_items'        => 'Add or remove Lesson Tags',
		'choose_from_most_used'      => 'Choose from the most used',
		'popular_items'              => 'Popular Lesson Tags',
		'search_items'               => 'Search Lesson Tag',
		'not_found'                  => 'Not Found',
		'no_terms'                   => 'No items',
		'items_list'                 => 'Lesson Tags list',
		'items_list_navigation'      => 'Lesson Tags list navigation',
	);
	$args = array(
		'labels'                     => $labels,
		'hierarchical'               => false,
		'public'                     => true,
		'show_ui'                    => true,
		'show_admin_column'          => true,
		'show_in_nav_menus'          => true,
		'show_tagcloud'              => true,
	);
	register_taxonomy( 'lesson_tags', array( 'mpcs-lesson' ), $args );
}

Line 35 associates the new taxonomy (lesson_tags) with the mpcs-lesson post type.

Now add the code for appending classes for lessons to lesson pages:

add_action('after_setup_theme', 'nwb_add_tax_to_single_action');
function nwb_add_tax_to_single_action($classes) {
	add_filter('body_class','nwb_add_tax_to_single');
	function nwb_add_tax_to_single($classes) {
		$this_post_type = get_post_type(get_the_ID());
		$post_type_cos = 'this-post-type_' . $this_post_type;
		if ( is_singular('mpcs-lesson') ) {
			global $post;
			$taxonomy_terms = get_the_terms($post->ID, 'lesson_tags');
			if ( $taxonomy_terms ) {
				foreach((get_the_terms($post->ID, 'lesson_tags')) as $term) {
					// *** Add category slug to the $classes array
					$classes[] = 'lesson-tag-' . $term->slug;
				}
			}
			$classes[] = $post_type_cos;
			// ***  return the $classes array
			return $classes;
		}
	}
}

Assuming I assigned the lesson_tag “video” to one of the lessons, the body element would look something like this (I’m omitting all of the classes that WordPress and MemberPress add, for clarity):

<body class="lesson-tag-video this-post-type_mpcs-lesson">

The lesson-tag-video comes from line 13; the this-post-type_mpcs-lesson, which represents the post type, comes from lines 6 and 16.

Remember Post Formats?

Post Formats were introduced in WordPress version 3.1. Initially at least, this feature performed essentially the same function as the snippets above: Namely, it allowed you to distinctively format posts based on one of the preset post formats defined by WordPress. These post formats are kinda-like categories or tags. Those preset formats — as of this writing — are (and I’ve copied from the above-referenced WordPress dot org page):

  • aside: Typically styled without a title. Similar to a Facebook note update.
  • gallery: A gallery of images. Post will likely contain a gallery shortcode and will have image attachments.
  • link: A link to another site. Themes may wish to use the first <a href=""> tag in the post content as the external link for that post. An alternative approach could be if the post consists only of a URL, then that will be the URL and the title (post_title) will be the name attached to the anchor for it.
  • image: A single image. The first <img> tag in the post could be considered the image. Alternatively, if the post consists only of a URL, that will be the image URL and the title of the post (post_title) will be the title attribute for the image.
  • quote: A quotation. Probably will contain a blockquote holding the quote content. Alternatively, the quote may be just the content, with the source/author being the title.
  • status: A short status update, similar to a Twitter status update.
  • video: A single video or video playlist. The first <video> tag or object/embed in the post content could be considered the video. Alternatively, if the post consists only of a URL, that will be the video URL. May also contain the video as an attachment to the post, if video support is enabled on the blog (like via a plugin).
  • audio: An audio file or playlist. Could be used for Podcasting.
  • chat: A chat transcript, like so:

Some of the formatting was accomplished by the WordPress “engine”; for example, the entry title of a post assigned the link post format would be converted to a clickable link. Much of the formatting, however, was accomplished through CSS. An appropriate class name (e.g., single-format-aside, single-format-gallery, single-format-link, etc.) is appended to the body element’s class property for targeting with CSS.

Here’s a sampling of CSS rules in the Twentyeleven style sheet (it’s long; click to expand):

/* =Aside
----------------------------------------------- */

.format-aside .entry-title,
.format-aside .entry-header .comments-link {
	display: none;
}
.singular .format-aside .entry-title {
	display: block;
}
.format-aside .entry-content {
	padding: 0;
}
.singular .format-aside .entry-content {
	padding: 1.625em 0 0;
}


/* =Link
----------------------------------------------- */

.format-link .entry-title,
.format-link .entry-header .comments-link {
	display: none;
}
.singular .format-link .entry-title {
	display: block;
}
.format-link .entry-content {
	padding: 0;
}
.singular .format-link .entry-content {
	padding: 1.625em 0 0;
}


/* =Gallery
----------------------------------------------- */

.format-gallery .gallery-thumb {
	float: left;
	display: block;
	margin: .375em 1.625em 0 0;
}


/* =Status
----------------------------------------------- */

.format-status .entry-title,
.format-status .entry-header .comments-link {
	display: none;
}
.singular .format-status .entry-title {
	display: block;
}
.format-status .entry-content {
	padding: 0;
}
.singular .format-status .entry-content {
	padding: 1.625em 0 0;
}
.format-status img.avatar {
	-moz-border-radius: 3px;
	border-radius: 3px;
	-webkit-box-shadow: 0 1px 2px #ccc;
	-moz-box-shadow: 0 1px 2px #ccc;
	box-shadow: 0 1px 2px #ccc;
	float: left;
	margin: 4px 10px 2px 0;
	padding: 0;
}


/* =Quote
----------------------------------------------- */

.format-quote blockquote {
	color: #555;
	font-size: 17px;
	margin: 0;
}


/* =Image
----------------------------------------------- */

.indexed.format-image .entry-header {
	min-height: 61px; /* Prevent the comment icon from colliding with the image when there is no title */
}
.indexed.format-image .entry-content {
	padding-top: 0.5em;
}
.indexed.format-image .entry-content p {
	margin: 1em 0;
}
.indexed.format-image .entry-content p:first-child,
.indexed.format-image .entry-content p:first-child a,
.indexed.format-image .entry-content p:first-child img {
	display: block;
	margin: 0;
}
.indexed.format-image .entry-content .wp-caption .wp-caption-text {
	margin: 0;
	padding-bottom: 1em;
}
.indexed.format-image footer.entry-meta {
	background: #ddd;
	overflow: hidden;
	padding: 4%;
	max-width: 96%;
}
.indexed.format-image div.entry-meta {
	display: inline-block;
	float: left;
	width: 35%;
}
.indexed.format-image div.entry-meta + div.entry-meta {
	float: none;
	width: 65%;
}
.indexed.format-image .entry-meta span.cat-links,
.indexed.format-image .entry-meta span.tag-links,
.indexed.format-image .entry-meta span.comments-link {
	display: block;
}
.indexed.format-image footer.entry-meta a {
	color: #444;
}
.indexed.format-image footer.entry-meta a:hover {
	color: #fff;
}
#content .indexed.format-image img {
	border: none;
	max-width: 100%;
	padding: 0;
}
.indexed.format-image .wp-caption {
	background: #111;
	margin-bottom: 0;
	max-width: 96%;
	padding: 2% 2% 0;
}
.indexed.format-image .wp-caption .wp-caption-text {
	color: #ddd;
}
.indexed.format-image .wp-caption .wp-caption-text:before {
	color: #444;
}
.indexed.format-image a:hover img {
	opacity: 0.8;
}

Which is better?

It’s not an either/or thing. Post formats have their place, and I experimented with them when they first came out. Frankly, though, I can’t remember the last time I used them. Conversely, I often use this “trick” of adding category and tag slugs to the body element (use case here) in order to distinctively style page elements.

Comments Welcome

Did this post help in any way? Do you have a better way to accomplish the same end? Do you use post formats? Questions about the code? Let me know what you think.

Like what you see? Share with others and join my mailing list. No long-term commitment, unsubscribe any time.

Related Posts

  1. Post Formats have NOT been removed from WordPress 3.6 core
  2. Child Themes – WordCamp ATL 2012 Presentation
  3. How to Override MemberPress Template Files
  4. Underlining for Emphasis: How to un-underline text on a Web page with CSS
  5. What to look for in WordPress themes: Pluggability

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

mailchimp signup

Subscribe to get notified when new articles are published. Unsubscribe any time. No spam. I promise. Check out my newsletter archives.

social

Twitter Facebook LinkedIn

Recent Articles

  • Post-Specific CSS for WordPress October 5, 2026
  • You built an online course, but they haven’t come. September 16, 2026
  • Custom MemberPress Pricing Pages December 19, 2025
  • CSS Data Attribute Override December 11, 2025
  • MemberPress Rules Using Custom Taxonomies and Custom Roles December 10, 2025

Filter By Category/Tag

Categories

  • Case Studies (8)
  • For Staff (1)
  • General (73)
  • Portfolio (7)
  • Reviews (14)
  • Snippets (24)
  • Techniques (52)

Popular Tags

Advanced Custom Fields Blogging Child Themes Content Marketing CSS Customer Service Custom Fields Custom Post Types Diagnostics Domain Names Facebook FooGallery Genesis Hosting HTML Images iPhone Libra Live Chat Marketing Media MemberPress MemberPress Courses Membership Sites Mobile-Friendly MySQL Photo Gallery php Pinterest Plugins Post Formats Pricing Project Management SEBA SEO Seth Godin Shortcodes Social Networking Surveys Taxonomies Twitter Video Web design Web forms WordPress

Footer

Background

Web Sites | WordPress Support | Web Applications.

Formally trained in liberal arts and education (I have a B.A. in Government from Harvard and studied Secondary Education at Rutgers Graduate School), I have honed my skills in the communication arts and sciences as a teacher, trainer, instructional designer, writer, photographer, calligrapher, helpdesk manager, database programmer, and multimedia developer.

(I've also been a group counselor, waiter, bartender, bicycle messenger boy, computer salesman, carpenter's helper, financial analyst, and school board president.)

Tech

Systems since 1983.
Web sites since 1994.
PHP since 2001.
WordPress since 2007.

Contact

Book Meeting
770-772-5134
Email Jeff
Send Money
All Ways

Copyright 2026, nSiteful Web Builders, Inc.

Cookies Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
View preferences
  • {title}
  • {title}
  • {title}
https://iframe.mediadelivery.net/embed/392008/42d18bc1-2adc-4741-b733-053d08d09c32
https://vz-000c5976-3ab.b-cdn.net/42d18bc1-2adc-4741-b733-053d08d09c32/play_720p.mp4

Receive occasional emails from Jeff