To show the current post’s categories in WordPress on a single post template you need a short list of category links, with markup you can style and a way to highlight or show only the main category.
This snippet prints the post’s categories as a list of links. The primary category gets an is-primary class: the one chosen in Yoast SEO when that plugin is active, otherwise the first category. One setting switches the list to the primary category only.
The older version of this post read $post without declaring it and printed a PHP warning, plus an error on posts without categories. Both are fixed.
The snippet
<?php
/**
* The current post's categories as links; the primary category gets a class.
* Scripts Organizer: Trigger location Conditions, Script location Shortcode.
*/
$dpc_primary_only = false; // true: show only the primary category.
$dpc_cats_post_id = get_the_ID();
$dpc_cats = $dpc_cats_post_id ? get_the_category( $dpc_cats_post_id ) : array();
if ( $dpc_cats ) {
// Primary category set with Yoast SEO, otherwise the first one.
$dpc_primary_id = (int) get_post_meta( $dpc_cats_post_id, '_yoast_wpseo_primary_category', true );
if ( ! in_array( $dpc_primary_id, wp_list_pluck( $dpc_cats, 'term_id' ), true ) ) {
$dpc_primary_id = (int) $dpc_cats[0]->term_id;
}
echo '<ul class="dpc-post-cats">';
foreach ( $dpc_cats as $dpc_cat ) {
$dpc_is_primary = ( (int) $dpc_cat->term_id === $dpc_primary_id );
if ( $dpc_primary_only && ! $dpc_is_primary ) {
continue;
}
printf(
'<li class="dpc-post-cats__item dpc-post-cats__item--%1$s%2$s"><a href="%3$s" rel="category tag">%4$s</a></li>',
esc_attr( $dpc_cat->slug ),
$dpc_is_primary ? ' is-primary' : '',
esc_url( get_category_link( $dpc_cat ) ),
esc_html( $dpc_cat->name )
);
}
echo '</ul>';
}
Add it with Scripts Organizer
In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Conditions, tick Shortcode under Script location (leave PHP unticked), paste the code into the PHP editor, keep Template on All and publish.
The block now shows its shortcode, for example [scorg_shortcode id="123"]. Paste it where the output should appear: a Shortcode block in the post or in a block theme template, or the shortcode element of your page builder’s single or archive template.
Scripts Organizer includes this file every time the shortcode renders, inside its own function. That is why the code has no function declarations (a second shortcode on the same page would fatal with “Cannot redeclare”), uses get_the_ID() or get_queried_object_id() instead of a bare $post, and prefixes its variables with dpc_.
How it works
get_the_ID()is the post being shown, on a single template and inside a loop. Without a post, or for post types without categories, the list is not printed at all.- The Yoast SEO primary category is read from
_yoast_wpseo_primary_category, but only used when the post still has that category. Without Yoast the first category is primary. - Each item has a class with the category slug, so you can colour categories individually, and the link has
rel="category tag"like WordPress’ own category links. Names, slugs and URLs are escaped.
Customise it
- Only the main category, like a breadcrumb: set
$dpc_primary_onlytotrue. - Inline instead of a list: replace
ulandliwithspantags and add a separator in CSS:.dpc-post-cats__item+.dpc-post-cats__item::before{content:", "}. - Custom taxonomies or tags with a class per term: see Show a post’s custom taxonomy terms.
- All categories of the site with the current one marked: see List categories with an active class.
Gotchas
- Other SEO plugins store the primary category under a different meta key. Change
_yoast_wpseo_primary_categoryto that key if it stores a term ID. - Block themes have a Post Terms block that lists categories without code; use this snippet when you need the primary class or the slug classes.
In the Scripts Organizer library Import it with one click from Scripts Organizer.