Blog / WordPress/ How to Exclude Sticky Posts from the WordPress Homepage Main Loop

How to Exclude Sticky Posts from the WordPress Homepage Main Loop

WordPress 首页主循环中排除置顶文章的完整指南

Why Exclude Sticky Posts from the Main Loop

In WordPress development, you might display sticky posts separately (e.g., via a custom block or widget) outside the main loop on your homepage. To prevent duplicate sticky post listings, you need to exclude them from the default main query, which normally shows sticky posts before recent posts.

Recommended Solution

While you may have seen solutions using query_posts(), this function is strongly discouraged because it replaces the main query entirely, often breaking pagination, plugin compatibility, and causing other side effects.

The correct approach is to use WordPress's pre_get_posts action hook, which safely modifies the main query parameters before execution.

Core Code

Add this code to your theme's functions.php file:

function exclude_sticky_posts($query) {
    // Only run for the front-end main query
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    // Apply only to the homepage
    if ( $query->is_home() ) {
        // Ignore sticky posts, show them in normal order
        $query->set( 'ignore_sticky_posts', 1 );
    }
}
add_action( 'pre_get_posts', 'exclude_sticky_posts' );

Code Explanation

  • is_admin(): Prevents the code from affecting the WordPress admin area.
  • $query->is_main_query(): Ensures only the site's primary query is modified, not secondary queries (widgets, menus, etc.).
  • $query->is_home(): Restricts the rule to the site's front page.
  • $query->set( 'ignore_sticky_posts', 1 ): The key parameter. Setting it to 1 or true tells WordPress not to force sticky posts to the top; all posts (including stickies) will follow normal sorting (by date, menu order, etc.).

Extended Applications

To exclude sticky posts on other pages (like category archives), modify the conditional. For example, for category pages:

if ( $query->is_category() ) {
    $query->set( 'ignore_sticky_posts', 1 );
}

You can combine conditions or apply to all archive pages:

// Exclude sticky posts on homepage and all archives (category, tag, author, date)
if ( $query->is_home() || $query->is_archive() ) {
    $query->set( 'ignore_sticky_posts', 1 );
}

Important Notes

  • This method only changes the display order. Sticky posts retain their status and will still appear at the top in other main queries where ignore_sticky_posts is not set.
  • If you call sticky posts separately elsewhere (using WP_Query or get_posts), you can control them with parameters like 'post__in' => get_option( 'sticky_posts' ); they won't be affected by the main query modification.
  • Before editing functions.php, consider creating a child theme or backing up the file.

Post a Comment

Your email will not be published. Required fields are marked with *.