For a normal category navigation list, WordPress already hides empty categories. Use wp_list_categories() with 'hide_empty' => true. If you also want the heading and surrounding section to disappear when no categories qualify, fetch the terms with get_categories() and render the wrapper only when the returned array is not empty.
Hide empty categories in a WordPress category list
wp_list_categories() displays a list of category links and uses hide_empty => true by default. Setting it explicitly makes the behavior clear in your template:
<ul>
<?php
wp_list_categories(
array(
'hide_empty' => true,
'title_li' => '',
)
);
?>
</ul>
hide_empty => trueexcludes categories that have no assigned posts.title_li => ''removes the function’s default title item, allowing your theme to provide its own heading.- The function prints the list by default. Set
'echo' => falsewhen you need to capture its HTML instead.
Hide the entire category section when no categories qualify
Filtering individual links does not automatically remove a heading or wrapper. Use get_categories(), test the returned array, and output the complete section only when it contains terms:
<?php
$categories = get_categories(
array(
'hide_empty' => true,
)
);
if ( ! empty( $categories ) ) {
echo '<section class="category-navigation">';
echo '<h2>' . esc_html__( 'Categories', 'textdomain' ) . '</h2>';
echo '<ul>';
foreach ( $categories as $category ) {
printf(
'<li><a href="%s">%s</a></li>',
esc_url( get_category_link( $category->term_id ) ),
esc_html( $category->name )
);
}
echo '</ul>';
echo '</section>';
}
?>
get_categories() returns an empty array when no categories match, so the heading, list, and section are all omitted in that case. Escape generated URLs and names as shown.
#1 Best Overall
Use the block editor instead of PHP
In the block editor, add a Categories List block and disable its option to show empty categories. The block can also show post counts and limit the display to top-level categories. This is the simplest approach when the list is managed in a page, template part, widget area, or site editor template rather than a PHP file.
Category lists and category archive pages are different
A category list is navigation: it outputs links to category archives. A category archive is the page displayed after a visitor follows one of those links. Conditional tags such as is_category() test whether the current request is a category archive; they do not determine whether an arbitrary category should appear in a navigation list.
When “has posts” means published posts only
The built-in hide_empty behavior is based on terms being assigned to posts. That is not automatically identical to “has at least one published post of a particular post type.” Drafts, private posts, custom post types, and taxonomy registration can change what a term count represents.
- For ordinary blog categories,
hide_empty => trueis usually the required test. - For a custom taxonomy, use
get_terms()with the taxonomy name and confirm that the taxonomy is registered for the intended post type. - If only published content should count, verify the site’s post-status and query configuration rather than assuming the default term count enforces that rule.
$terms = get_terms(
array(
'taxonomy' => 'your_taxonomy',
'hide_empty' => true,
)
);
Set hide_empty => false only when you intentionally want unused terms included.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteQuick Recap
Best Value
Rank #4
Which implementation should you choose?
| Requirement | Recommended method |
|---|---|
| Hide empty links in a PHP category menu | wp_list_categories( array( 'hide_empty' => true ) ) |
| Hide the heading and wrapper as well | Call get_categories(), then render only when the array is non-empty |
| Build the list in the block editor | Categories List block with “Show empty categories” disabled |
| Display a custom taxonomy | get_terms() with the intended taxonomy and hide_empty => true |
Common mistakes
- Using
is_category()to filter a navigation list. It checks the current archive request, not each term’s content. - Leaving a “Categories” heading outside the conditional. The heading remains even when the list is empty.
- Setting
hide_empty => falseunintentionally. That displays categories with no assigned posts. - Assuming an assigned draft or private post should count as a published post. Confirm the site’s content and status rules when that distinction matters.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

