Okay I am starting to wonder if it is even possible to do this! As I've found very little info on the matter online. This is a fresh WP install that I've been experimenting on so that I can work in a more simplified environment (rather than try to solve the full problem itself on my live client's website if that makes sense).

I'm trying to display a total of 3 posts using query_posts(). I want the sticky posts to show first, and then for the remainder of the loop to consist of none-stickies.

As you can see, it is loading too many posts (6 in total, which is all of the posts on the site):


Here is the code I'm using:

<?php wp_reset_query(); ?>


    // sticky posts first

    $sticky = get_option('sticky_posts');

      'post__in' => $sticky,
      'posts_per_page' => 3,
      'post_type' => 'post'

    get_template_part('loop', 'query-sticky' );



    // none-stickies for remainder of loop

      'post__not_in' => $sticky

    get_template_part('loop', 'query-sticky-none' );



I assume that the second loop is trying to display 10 posts as per my settings in WP. I was hoping that the posts_per_page param in the first loop would maybe carry over to the second.

Because I of course can't specify posts_per_page again in the second loop as there would be more than 3 posts displayed overall.

Is it actually possible to get sticky posts to work in this way? Or is the only way to get them to work properly to use them on the 'posts' page in WordPress? Not using a custom query?

  • Never ever use query_posts. Secondly, you are running you second query inside the first one, which is why you get a half ton posts back. Use WP_Query to rewrite your code. Commented Feb 13, 2015 at 15:26

1 Answer 1


Give this a try. It replaces query_posts(), which you should never use (it kills unicorns) with WP_Query.

Basically it first queries your sticky posts and then, if there were less than your required 3 posts, it will perform another query for the relavent number of posts.

/** Grab the sticky post ID's */
$sticky = get_option('sticky_posts');

/** Query the sticky posts */
$args = array(
    'post__in'          => $sticky,
    'posts_per_page'    => 3,
    'post_type'         => 'post'
$sq = new WP_Query($args);

/** Count the number of post returned by this query */
$sq_count = $sq->post_count;

/** Output your sticky posts */
get_template_part('loop', 'query-sticky'); // You'll need to globalize `$sq` in this template

/** Check to see if any non-sticky posts need to be output */
if($sq_count < 3) :

    $num_posts = 3 - $sq_count;
    /** Query the non-sticky posts */
    $sticky = get_option('sticky_posts');
    $args = array(
        'post__not_in'      => $sticky,
        'posts_per_page'    => $num_posts,
        'post_type'         => 'post'
    $nq = new WP_Query($args);
    /** Output your non-sticky posts */
    get_template_part('loop', 'query-sticky-none'); // You'll need to globalize `$nq` in this template

"I don't want to globalize in my templates"

If you don't want to have to globalize the $sq and $nq variables in your templates, rather than get_template_part() you could use locate_template() -

  • Thanks a lot, I never would have thought of all that! Worked like a treat :D
    – user39214
    Commented Feb 18, 2015 at 5:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.