WP_Query: Exclude a Category (and Paginated Archives)
If you want to display posts on your WordPress site but exclude one or more categories — including on paginated archive pages — the WP_Query
class is your go-to solution. This tutorial shows you how to exclude categories properly, ensuring pagination works seamlessly without showing posts from unwanted categories.
When to Use This
- You want to customize your blog or archive pages to hide posts from specific categories.
- You need to exclude categories on paginated archive pages without breaking pagination.
- You want to create custom loops or queries that omit certain categories.
Quick Fix: Exclude Categories in WP_Query
- Use the
category__not_in
parameter inWP_Query
to exclude categories by ID. - Ensure pagination parameters are correctly passed to maintain paginated archives.
- Add the code snippet to your theme’s
functions.php
or a custom plugin. - Test on archive and paginated pages to confirm excluded categories don’t appear.
Why This Happens
By default, WordPress queries include posts from all categories unless filtered. Using category__not_in
tells WordPress to exclude posts assigned to specific category IDs. However, if pagination is not handled correctly, excluding categories can cause pagination to break or display unexpected results because the total post count changes.
Properly passing the current page number and using WP_Query
with exclusion parameters ensures WordPress calculates pagination based on the filtered posts, maintaining correct page counts and navigation.
Step-by-Step: Exclude a Category with Pagination Support
- Identify the category ID(s) you want to exclude. You can find this in the WordPress admin under Posts → Categories. Hover over a category name and note the ID from the URL (e.g.,
tag_ID=5
). - Create a custom query using
WP_Query
with thecategory__not_in
parameter and pagination support.
<?php
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
'paged' => $paged,
'category__not_in' => array(5), // Replace 5 with your category ID(s)
);
$custom_query = new WP_Query( $args );
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) : $custom_query->the_post();
the_title('<h2>', '</h2>');
the_excerpt();
endwhile;
// Pagination
echo paginate_links( array(
'total' => $custom_query->max_num_pages,
'current' => $paged,
) );
wp_reset_postdata();
else :
echo '<p>No posts found.</p>';
endif;
?>
Add via functions.php or Mini-Plugin
You can add the above code directly in a custom page template or inside a shortcode function for easier reuse. Here is an example shortcode you can add to your theme’s functions.php
or a small plugin file:
<?php
function exclude_category_shortcode( $atts ) {
$atts = shortcode_atts( array(
'exclude' => '', // comma-separated category IDs
'posts_per_page' => 5,
), $atts, 'exclude_category' );
$exclude_ids = array_map( 'intval', explode( ',', $atts['exclude'] ) );
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'post',
'posts_per_page' => intval( $atts['posts_per_page'] ),
'paged' => $paged,
'category__not_in' => $exclude_ids,
);
$query = new WP_Query( $args );
ob_start();
if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
echo '<h2>' . get_the_title() . '</h2>';
echo get_the_excerpt();
endwhile;
echo paginate_links( array(
'total' => $query->max_num_pages,
'current' => $paged,
) );
wp_reset_postdata();
else :
echo '<p>No posts found.</p>';
endif;
return ob_get_clean();
}
add_shortcode( 'exclude_category', 'exclude_category_shortcode' );
?>
Use the shortcode in posts or pages like this:
[exclude_category exclude="5,7" posts_per_page="10"]
Testing
- Place the code in your theme or use the shortcode on a page.
- Visit the page and verify posts from the excluded categories do not appear.
- Navigate to paginated pages (e.g., /page/2/) and confirm pagination works and excluded categories remain hidden.
- Check for any 404 errors or empty pages and adjust
posts_per_page
or category IDs if needed.
Variations
- Exclude multiple categories: Pass multiple IDs in the array, e.g.,
'category__not_in' => array(5, 7, 9)
. - Exclude by slug: Use
tax_query
instead ofcategory__not_in
for more complex queries. - Exclude categories on main blog page: Use the
pre_get_posts
action hook to modify the main query.
Works on
Environment | Notes |
---|---|
Apache | Fully compatible; standard WordPress setup. |
Nginx | Works as expected; ensure permalinks are configured correctly. |
LiteSpeed | Compatible; no special configuration needed. | Developer Snippets Tags:Category, Loop, WP_Query