Prevent Posts in a Category From Displaying in WordPress’ Loop

By  on  

This code snippet has become a WordPress plugin!

Categories are obviously a major "classification" utility for websites and blogs that use WordPress.  Sometimes you want a category to represent more than just a basic post subject classification -- you may want a category of your blog to represent a link and writeup to an external site or may want to display their posts in a different way.  On this blog, I've added a "Quick Tips" category which are very short posts with tiny snippets of code that (quickly) detail how to do something simple.  I want those posts to display on listing pages, but not on the homepage.  I've seen some treacherous code to accomplish this feat, but luckily I've found a much cleaner way to prevent posts in a given category from displaying on a homepage.

The WordPress PHP

WordPress' API provides a pre_get_posts action which allows for additional pre-query logic:

// No "Quick Tips" on the homepage
function preventHomepageTips($query) {
	if($query->is_home() && $query->is_main_query()) {
		$query->set('cat', '-40'); // 40 is Quick Tips's category ID
	}
}
add_action('pre_get_posts', 'preventHomepageTips');

The custom function above is added as a WordPress action, usually within your functions.php file.  It's important you know the ID of the category or categories you don't want displaying in the main loop.  A dash is placed before said category ID.  To prevent multiple categories, separate them by commas:

$query->set('cat', '-40,-52');

If you simply want to prevent posts from displaying on the homepage but don't want to effect subsequent archive pages, you could add another hackish conditional:

if($query->is_home() && $query->is_main_query() && $_SERVER['REQUEST_URI'] == '/') {

This is an incredibly useful snippet that can be used for any number of purposes.  Chris Coyier, for example, uses a special category for his "Hot Links" posts (links to external websites) which he obviously doesn't displaying within the main loop.  There you have it though -- preventing posts in a category from displaying the loop!

Recent Features

  • By
    CSS Filters

    CSS filter support recently landed within WebKit nightlies. CSS filters provide a method for modifying the rendering of a basic DOM element, image, or video. CSS filters allow for blurring, warping, and modifying the color intensity of elements. Let's have...

  • By
    Page Visibility API

    One event that's always been lacking within the document is a signal for when the user is looking at a given tab, or another tab. When does the user switch off our site to look at something else? When do they come back?

Incredible Demos

  • By
    CSS Kwicks

    One of the effects that made me excited about client side and JavaScript was the Kwicks effect.  Take a list of items and react to them accordingly when hovered.  Simple, sweet.  The effect was originally created with JavaScript but come five years later, our...

  • By
    Display Images as Grayscale with CSS Filters

    CSS filters aren't yet widely supported but they are indeed impressive and a modern need for web imagery.  CSS filters allow you to modify the display of images in a variety of ways, one of those ways being displaying images as grayscale. Doing so requires the...

Discussion

  1. You the man.

  2. Hi there –

    I found your page while searching for something very similar to what you’ve done here, but instead of preventing a post from showing up on the homepage, I want to prevent it from showing up in a specific category.

    Here’s the thing: I have a category Cuisines and subcategories Italian, French, Spanish, etc. Each of those subcats has various recipes, as well as a post for the subcat itself (e.g., check out my Italian recipes!) I want the latter not to show up in the subcat, because obviously if you click them, they just link back to the same page you’re already on. I wonder if there’s an easy way to modify your code to accomplish this?

  3. Perfect! This is exactly what I was looking for! Thanks for sharing!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!