I’m using the following bit of code to highlight sticky posts:
<?php if (is_sticky()) : ?>
<div class="col-md-12 box-01">
<div class="content">
<?php endif; ?>
The only thing is, I only want to highlight the stickies that show at the top of the page… not when they’re repeated further down the list of posts.
For example, I noticed that when I click the ‘Next’ link to go to the next page or posts, the stickies show up again. And because of my code, they’re highlighted with the new styles in the same way as they are at the top.
Is there any kind of tag I can use to target sticky posts but only those that are stuck at the top? Rather than those further down?
I hope that makes sense…
1 Answer
Strange that stickies aren’t completely unset from the main loop on paged pages but only on the first page. If we look at the source, we will see that stickies are only unset from the main loop if they are on the first page. So we have two options here depending on what you exactly need
OPTION 1
If you need to keep your stickies in the loop on paged pages and just remove the styling, you can make use of the is_paged()
condition in conjuction with your condition
if ( is_sticky()
&& !is_paged()
) {
// Add your styling here
}
OPTION 2.1
Completely remove stickies from paged pages
add_action( 'pre_get_posts', function ( $q )
{
if ( $q->is_home() // Only target the home page
&& $q->is_main_query() // Only target the main query
&& $q->is_paged() // Only target paged pages
) {
// Remove stickies
$q->set( 'post__not_in', get_option( 'sticky_posts' ) );
}
});
I’m just thinking that if we use this option that we will need to adjust $found_posts
to compensate for pagination on the first page. WP_Query
throws us a curveball here as we cannot set post__not_in
on page one as this will explicitely remove any sticky post from the sticky posts array if these specific posts aren’t on the first page.
I will investigate this and post anything extra that would be relevant to this issue
EDIT
There is an issue with pagination, so we will need to adjust the $found_posts
property to adjust for pagination
add_filter( 'found_posts', function( $found_posts, \WP_Query $q )
{
if ( $q->is_home()
&& $q->is_main_query()
&& !$q->is_paged()
) {
// Get the sticky posts array
$stickies = get_option( 'sticky_posts' );
// Get all the post ID's from the first page
$ids = $q->posts;
// Remove all the current ids from the current sticky posts array
$stickies = array_diff( $stickies, $ids );
$found_posts = $found_posts - count( $stickies );
}
return $found_posts;
}, 10, 2 );
OPTION 2.2
I always tend to use the following right off the back to handle my sticky posts. This completely removes sticky posts from the main query and then it gets added back to via the the_posts
filter
add_action( 'pre_get_posts', function ( $q )
{
if ( $q->is_home()
&& $q->is_main_query()
) {
$q->set( 'ignore_sticky_posts', 1 );
$q->set( 'post__not_in', get_option( 'sticky_posts' ) );
add_filter( 'the_posts', function( $posts, \WP_Query $q )
{
// Only do this for the first page
if ( $q->is_paged() )
return $posts;
$stickies = get_option( 'sticky_posts' );
// Check if we have stickies
if ( !$stickies )
return $posts;
$args = [
'posts_per_page' => count( $stickies ),
'post__in' => $stickies,
];
$sticky_posts = get_posts( $args );
// Merge the array
$posts = array_merge( $sticky_posts, $posts );
return $posts;
}, 10, 2 );
}
});