The post_class()
function is one of the many functions provided by WordPress to facilitate theme development. As the name suggests, the post_class()
function outputs an HTML class attribute and sets its value to classes related to the post being output.
The correct way to use the function is to add it to the HTML tag that serves as the container for the post content:
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
The post classes
The number and the name of the classes output by the post_class()
function depends on the properties attached to a specific post. Here is an overview of the different possibilities and the contexts in which they are added.
hAtom compliance
WordPress respects the hAtom microformat. Therefore every post has an .hentry
class added to it to respect the specification. This class is a great way to target both posts and pages in your CSS.
Post ID
An example of the post ID class might be .post-26
. The number at the end of the class corresponds to the ID of this post in the database. As these IDs are unique, this class is a great way to target individual posts in your CSS. Something to keep in mind is that the post ID class starts with .post-
, even for pages.
Post type
The post type identifies the type of content that is displayed. By default, WordPress includes posts and pages as content types. This information is output twice, once only the name of the post type (so .post
and .page
) and once prefixed with type-
(so .type-post
and .type-page
).
When the theme displays a custom post type, the name of the post type that is output corresponds to the first parameter of the register_post_type()
function. As an example the classes for the Portfolio Custom Post Type in Jetpack are .jetpack-portfolio
and .type-jetpack-portfolio
.
Post status
The post status determines how WordPress handles a specific post. Draft posts for example are not displayed on the front end, and private posts are only visible on the front end for users for administrator access. The status is added with status-
as a prefix, so .status-published
or .status-private
for example.
Password protected posts
Posts that are only visible after having entered the post password receive the .post-password-required
class.
Sticky
Posts that are marked as sticky receive the .sticky
class, but only when they are displayed on the first page of the blog home. On single views or when they are displayed in other types of archives, this class won’t be added.
Post thumbnails
When the activate theme has declared support for post thumbnails, and the post has a featured image set, the .has-post-thumbnail
class is added.
Post Formats
The format of the current post prepended with format-
. The possible values for the format are aside
, audio
, chat
, gallery
, image
, link
, quote
, status
and video
.
These classes are added independently of whether the theme has declared support for post formats or whether the theme supports the particular format in question. The determining factor for the output of these classes are whether the post type supports post formats. This means that these classes will get added to posts, but not to pages, as pages don’t support post formats out of the box.
Categories and Tags
The categories and tags associated to a particular post will be added with the category-
and tag-
prefix. The names of the categories and tags are turned into slugs, meaning that they are all lowercase, without special characters and with dashes instead of spaces.
Adding or removing post classes
The post_class()
function accepts two optional arguments, $class
and $post_id
. It is possible to add classes by passing them either as a string or an array as the $class
argument.
However, a better alternative is to use the post_class
filter. By using a filter, all classes are added and removed in a single place, and the classes that are added aren’t dispersed among the templates files. Additionally this avoids duplication if you want to add classes in different contexts, and it makes it easier for child themes to remove or add their own classes.
Adding classes
Imagine that you want to add specific styles to posts that don’t have a comment yet. How can we do that?
function theme_slug_post_classes( $classes, $class, $post_id ) { if ( 0 == get_comments_number( $post_id ) ) { $classes[] = 'no-comments'; } return $classes; } add_filter( 'post_class', 'theme_slug_post_classes', 10, 3 );
The first thing we need to do is add a custom function to our theme’s functions.php
file. In this tutorial, we use a generic prefix; when using this code, please prefix the function correctly.
Our function accepts three parameters ($classes
, $class
, and $post_id
), because these are the variables that WordPress passes through this filter:
$classes
is an array of classes for the post.$class
is a comma separated list of additional classes that may have been added directly via the$class
parameter of thepost_class()
function. If no classes were added, this variable is going to be an empty string.$post_id
is an integer and it corresponds to the unique ID of the post.
The $classes
array is what we are going to use to add or remove classes. The other two variables provide context for this filter.
In this case, we can use the $post_id
variable and pass it to get_comments_number()
. This function will then return the number of comments for the post. If there are no comments, we add the .no-comments
class to the $classes
array.
At the end of the function, we return this array. It is important to do this even when you don’t modify the $classes
array. If you don’t return any data or return malformed data, this will break the site.
As we are using the additional variables passed by the post_class
filter, we need to add to arguments to the add_filter()
call:
- The
10
at the end corresponds to the priority with which the filter runs. This is the standard priority, and there is no need to change this. - The
3
corresponds to the number of variables passed. If you only pass two variables, you need to set this to2
. If you only pass one parameter, this argument and the previous argument can be omitted.
Removing classes
Removing classes works very much the same way. Imagine that we create a child theme for a theme that adds an extra .box
class to every post, and we want to remove this.
function theme_slug_post_classes( $classes ) { $class_key = array_search( 'box', $classes ); if ( false !== $class_key ) { unset( $classes[ $class_key ] ); } return $classes; } add_filter( 'post_class', 'theme_slug_post_classes' );
As $classes
is an array, we need to know the key of the array element containing the undesired .box
class. This is because the unset()
function needs this key in order to remove the corresponding value from the array.
So first we use the array_search()
function to look for the box value in our $classes
array. The return value of this function is then stored in the $class_key
variable.
When the box
value isn’t found, $class_key
will be set to false
, and the $classes
array won’t be modified. But when the $class_key
contains an integer, this condition will pass and the entry containing the box value will be removed from the $classes
array.
In this example, we have removed an extra class. You should avoid removing classes added by WordPress itself, as plugins or user customizations might rely on these classes always being present.
Leveraging post classes in CSS
Now that we have seen how to interact with the post_class()
function in PHP, we will look at a few quick tips for how this function can help you write better CSS.
- Use the core provided classes: When you write your CSS, look at the HTML source code. Often WordPress provides you with the right classes that you can leverage in your CSS. In fact most themes can get by without modifying the post classes at all.
- Use the body classes: The
body_class()
function works similar topost_class()
. Together they can be used to target any post in any context. If you want to add specific styles to every post or page displayed on the search results page for example, all you need is the.search .hentry
selector to target these entries. - Use custom parent selectors: When using secondary queries (via
WP_Query
) for example on a custom page template, developers often run into trouble because there is no easy way to only target the posts output by the secondary query. As with the previous tip, just adding adiv
element around the output of the loop will allow you style these posts by simply using the parent selector of the container element.
Conclusion
As we have seen post_class()
is a very useful function and it will make styling your themes a lot easier if used properly. If you’ve got any questions, let me know in the comments.
Happy theming!