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
    I’m an Impostor

    This is the hardest thing I've ever had to write, much less admit to myself.  I've written resignation letters from jobs I've loved, I've ended relationships, I've failed at a host of tasks, and let myself down in my life.  All of those feelings were very...

Incredible Demos

  • By
    jQuery Chosen Plugin

    Without a doubt, my least favorite form element is the SELECT element.  The element is almost unstylable, looks different across platforms, has had inconsistent value access, and disaster that is the result of multiple=true is, well, a disaster.  Needless to say, whenever a developer goes...

  • By
    Link Nudging with CSS3 Animations

    One of the more popular and simple effects I've featured on this blog over the past year has been linking nudging.  I've created this effect with three flavors of JavaScript:  MooTools, jQuery, and even the Dojo Toolkit.  Luckily CSS3 (almost) allows us to ditch...

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!