Let's say I have the posts foo, bar and baz. They are published in the following order:

1. foo
2. bar
3. baz

If I call get_previous_post() while on the single.php of baz, I'll get bar.

I set bar as sticky. Now, the posts are ordered like so:

2. bar
1. foo
3. baz

If I call get_previous_post() while viewing baz, I still get bar, because it's chronologically the previous post. However, in the actual "loop display" of the posts, foo is previous.


How do I get the "visually previous" post in WordPress?

Edit: Basically, I want get_previous_post() to process sticky posts as the newest, regardless of their post date.

  • So to make this clear: You are inside (the loop / a specific post) - meaning get_post() will return the viewed post - and want the first previous/next post that is not a sticky? Actually seems a bit complicated, as get_adjacent_post() doesn't take post ID into account, so you can't call it that easily on another post beside the current one ...
    – kero
    Commented Jul 8, 2017 at 11:56
  • I have a listing on my index.php as described in my question. When I'm on the single.php of a post, I want to get the previous post as seen on the listing.
    – dodov
    Commented Jul 8, 2017 at 12:07

1 Answer 1


Ok, this might be overcomplicating things a bit, but at least it should work (untested).

Just call the function like so

get_adjacent_without_sticky( get_the_ID(), true); // get previous post
get_adjacent_without_sticky( get_the_ID(), false); // get next post

This could have been solved easily, if get_previous_post() allowed for an ID to pass and not only run it in the context of the current post. Now you could copy the function code of get_adjacent_post() and adjust it to your needs, but I don't like messing directly with SQL inside WordPress, so using the common functions it should work like this:

function get_adjacent_without_sticky($id, $previous = true) {

    // get date of current post as reference
    $date = explode('.', get_the_date('d.m.Y', $id));
    $date_array = array(
        'day' => $date[0],
        'month' => $date[1],
        'year' => $date[2],

    // for previous post we need the first post before current one
    if ($previous) {
        $order = 'DESC';
        $date_query = array(
            'before' => $date_array,
    // for next post we need the first post after current one
    else {
        $order = 'ASC';
        $date_query = array(
            'after' => $date_array,

    $args = array(
        // order sticky posts as regular ones
        'ignore_sticky_posts' => 1,
        // get only the one post we want
        'posts_per_page' => 1,
        'order' => $order,
        'orderby' => 'date',
        'date_query' => $date_query,

    // now run that query
    $the_query = new WP_Query($args);
    if ($the_query->have_posts()) {
        $result = get_post( get_the_ID() );
    } else {
        $result = NULL;
    wp_reset_postdata(); // Restore original Post Data

    return $result;

Related topics:

(My answer is bascially these two sources combined into a function.)

  • Actually, I want to have sticky posts. I simply want to display the previous post as seen on the listing. By default, get_previous_post() returns the chronologically previous post. It doesn't care whether the post is sticky or not. I think this would explain it best: If I set the oldest post as sticky, I want get_previous_post() to process it as the newest.
    – dodov
    Commented Jul 8, 2017 at 12:31
  • Okay, sorry. Then simply removing 'post__not_in' => $sticky, should work, because ignore_sticky_posts will make them sorted regularly
    – kero
    Commented Jul 8, 2017 at 12:45
  • @HristiyanDodov Have you seen the update/my last comment?
    – kero
    Commented Jul 8, 2017 at 17:01

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.