The Lodge is members-only design/dev videos and Office Hours.

Next Office Hours Session: "Implementing an SVG Icon System" Nov 30 - 6:00 PM Eastern

Paginate Custom Post Types

Last updated on:
  $temp = $wp_query; 
  $wp_query = null; 
  $wp_query = new WP_Query(); 

  while ($wp_query->have_posts()) : $wp_query->the_post(); 

  <!-- LOOP: Usual Post Template Stuff Here-->

<?php endwhile; ?>

    <?php previous_posts_link('&laquo; Newer') ?>
    <?php next_posts_link('Older &raquo;') ?>

  $wp_query = null; 
  $wp_query = $temp;  // Reset


  1. Dutch
    Permalink to comment#

    Something went wrong. Missing code tags?

  2. ins

    Missing code here? I really want this!!

    • Jake
      Permalink to comment#

      This helped me immensely, thanks for posting. Using the 3rd post in that topic I got my taxonomy pagination working as well. Even though the author claims his doesn’t paginate properly it seems to work fine for me.

  3. Benjamin
    Permalink to comment#

    It’s ridiculous that it hasn’t been updated or at least pulled down if 90% of the code is missing.

  4. Reinaldo
    Permalink to comment#

    This don’t work!

  5. Alex Pivtorak
    Permalink to comment#

    Oh, I’ll pray to God to give you much health in your life, Chris. You just saved so much time for me.
    Thanks a lot!!!!

    to Reinaldo > it works, even without any post types. I used it on the archives.php page, which shows all my categories and archives there.

  6. Andy
    Permalink to comment#

    Hi, this seems to half way work for me. I have the custom post type displaying correctly, but when I click on the “older” link it goes to /page/2/ but the posts stay the same as the previous page. So its not showing me the older posts and the “newer” link also does not show up on /page/2/. Anny suggestions would be great! Thanks!

  7. Tirumal
    Permalink to comment#

    Thanks, Worked like charm!! :)

  8. beefchimi
    Permalink to comment#

    I am having the same problem as andy… I get a Older link to page 2… but upon clicking that link, page2 contains the exact same posts, and the Older link takes me to the same destination, over and over again.

    • a
      Permalink to comment#

      Did you ever get this working? I am having the same problem and would appreciate any insight. Thanks in advance.

  9. KF
    Permalink to comment#

    There are a couple of custom loop examples towards the bottom of this page:

    For me, query_posts seems to work more reliably when it comes to pagination.

  10. Tirumal
    Permalink to comment#

    Here is a link for custom post type numeric pagination on my blog ->

  11. Nathan Jones
    Permalink to comment#


    This worked like a charm for the Testimonials custom post type I just finished working on for a client:

    There’s definitely a reason I donated to your Kickstarter… If ever I Google anything CSS or WP related, CSS-tricks is always right there with the right answer.

    Thanks Chris!

  12. Anthuan Vasquez
    Permalink to comment#

    In this line


    how i do include several post types?

    fox example

    • Ryan
      Permalink to comment#

      => ‘6’,
      ‘post_type’ => array(
      ‘paged’ => $paged

  13. Quran
    Permalink to comment#

    Thanks for this post, it was very helpful!

  14. simon
    Permalink to comment#

    Thank you so much for posting this…. after 7 hours of pulling my hair out and trying everything, this solution enabled the next/previous pages.
    I’m using custom post type categories and combined this code as below, to select the current category and display a loop of posts in the current category

    $current_cat = get_query_var(‘cat’);
    $temp = $wp_query;
    $wp_query = null;
    $wp_query = new WP_Query();
    ‘paged’ => $paged,
    ‘posts_per_page’ => 6,
    ‘cat’=> $current_cat

    while ($wp_query->have_posts()) : $wp_query->the_post();

    endwhile; // End the loop.

    <?php previous_posts_link( __( '< Newer Articles’, ‘twentyten’ ) ); ?>
    <?php next_posts_link( __( 'Older Articles >’, ‘twentyten’ ) ); ?>

    $wp_query = null;
    $wp_query = $temp; // Reset

    Hope this helps others
    This blog breaks my code so I’ve had to remove all php tags, but you can see the make up of the code

  15. marc2800
    Permalink to comment#

    Hi, i have lost 4 hours but with his code ITS WORK !

    Thanks a lot friend !

  16. Abel Cabans
    Permalink to comment#

    This didn’t worked for me because i tried to did this in my homepage, that was my problem i found a simply fix for paginate custom posts types in our homepages.

    Hope this code can help someone :)

    //Fix homepage pagination
    if ( get_query_var('paged') ) {
        $paged = get_query_var('paged');
    } else if ( get_query_var('page') ) {
        $paged = get_query_var('page');
    } else {
        $paged = 1;
    $args = array('post_type' => 'custom_post_type', 'paged' => $paged );
    $temp = $wp_query; 
    $wp_query = null; 
    $wp_query = new WP_Query(); 
    $wp_query->query( $args ); 
    while( ...

    • Erwin Chrisman Hendry
      Permalink to comment#

      Hi..this code is working for me right now. But there’s one problem : Page not found always showed up at the title bar. How can I fix this?

    • Kris
      Permalink to comment#

      Thanks, Abel! That’s just what I needed. I was pulling my hair out, because I got the “/page/2/” structure but no new posts. Your code did the trick.

    • Harry
      Permalink to comment#

      Thanks, Abel!

    • Ricky Cox

      Thanks Able, that’s what I needed.

  17. Anderson
    Permalink to comment#

    Dont work with offset


    With offset all pages have first post.

    • Anderson
      Permalink to comment#

      Now work xD

      $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; 
      $offset = ( 1 * $paged ) - 0; 
      $args=array('paged'=>$paged, 'posts_per_page'=>1, 'post_type'=>'yourCPT', 'offset' => $offset); 
      while ( $wp_query->have_posts() ) : $wp_query->the_post(); 
  18. Amber Weinberg
    Permalink to comment#

    Sigh, this doesn’t work when using it on index.php :( Can’t seem to get anything working

    • Catapult
      Permalink to comment#

      Hi Amber

      Abel Cabans code a few comments up worked for me on index.php

  19. Derek
    Permalink to comment#


    I had two custom post types: Photo and Poetry.
    I had two pages to display the query using your code: Gallery and Poetry.

    Gallery worked. Poetry didnt. Any guesses as to why?!

    I was going CRAZY for two days now…copied and pasted random code from all around the net….


    It seems that your page here is an anchor for all the others regarding CPT and Pagination. So, hopefully word gets around. I wish I could take out an ad on TV for this one

    • Derek
      Permalink to comment#

      As a guide…here was my gallery.php template…for the PAGE


      while ($wp_query->have_posts()) : $wp_query->the_post();

                      <div class="post" class="group">
                          <a href="<?php the_permalink(); ?>"><?php the_post_thumbnail( array(120,120)); ?></a>
  20. Silver Gold
    Permalink to comment#


    Try this:

    Solution of Paging for Custom Posts Type

    Hopefully, it will help you.

  21. Jeromy
    Permalink to comment#


    Works awesome. Thanks!

  22. Jake
    Permalink to comment#

    This works fine for me if I use it to display the custom post type on a page. However for some reason if I use the exact same code on ‘catalogue-archive.php’ it breaks the pagination. Any ideas on what’s going on there?

  23. Rik
    Permalink to comment#

    Hi, Thanks a lot. It works fine. I have one question. What do I have to add if I want to show custom post types from a specific Author?

    • Erwin Chrisman
      Permalink to comment#

      @Rik : You can use this

      $paged = ( get_query_var( ‘paged’ ) ) ? get_query_var( ‘paged’ ) : 1;
      $offset = ( 1 * $paged ) – 0;
      $args=array(‘paged’=>$paged, ‘posts_per_page’=>1, ‘post_type’=>’yourCPT’, ‘offset’ => $offset, ‘author_name’=>’yourname’);
      while ( $wp_query->have_posts() ) : $wp_query->the_post();

    • Rik
      Permalink to comment#

      Hi Erwin, thanks for your reaction. it doesn’t work at all. I’m sorry.
      I found another solution. This one and it works partially.

      $temp = $wp_query;
      $wp_query = null;
      $wp_query = new WP_Query();

      while ($wp_query->have_posts()) : $wp_query->the_post();

      But I have another problem now. At this moment it counts for all excisting authors 8 pages with 10 posts . So when there is an author with 18 posts it also counts 8 pages instead of 2. When I click page 3 it gives a 404. What can I do about that?

  24. Mark Szymanski
    Permalink to comment#

    Is the reset used above

    $wp_query = null;
    $wp_query = $temp; // Reset

    better, or the same as



  25. neil
    Permalink to comment#

    Here’s a weird one if I change the query variable to $loop it doesn’t work, but if its $wp_query it does????

  26. Trisha
    Permalink to comment#

    Amazing, this is the only code out there that works! (you probably already knew that)

    Im using this to click through all posts in a custom taxonomy (category).
    Is there a way to only show prev/next posts for the current taxonomy?

    • Mark

      Hello Trisha,
      I am looking to do the same – paginate the current taxonomy – did you end up getting it to work?

  27. Bryan
    Permalink to comment#

    I’ve been having issues with this for awhile now and can’t see to get it working on The more videos button gets clicked and only goes to page 2. There should be a page 3 but not sure why it’s stopping. Not sure if its a code problem, infinite scroll problem, or custom post type problem.

    In order to get it somewhat working properly, I have the reading part in the admin set to 3 posts, I want it to display 6 posts on the homepage, category pages, etc. But when I change the code to try to that, and you click on more videos button, nothing pops up. So I have to put 3 posts in the reading section in order to getting at least working. But it’s not desired to have 3 posts per page in the subcategory templates. If I change the posts 1 posts per page it will load all the videos, but I don’t want that because it will look all weird on the category pages. Any ideas on how to get this working right??

  28. Matt Prescott
    Permalink to comment#

    Cheers Chris, worked a treat!

  29. Daniel Pollitt

    This is the fixed that worked for me. I modified Chris’ original code with just one minor change: I added is_home right after is_tag

    add_filter(‘pre_get_posts’, ‘query_post_type’);
    function query_post_type($query) {
    if(is_category() || is_tag() || is_home()) {
    $post_type = get_query_var(‘post_type’);
    $post_type = $post_type;
    $post_type = array(‘post’, ‘page’, ‘videos’,’short-stories’, ‘long-stories’, ‘nav_menu_item’);
    return $query;

  30. Brad Dalton

    function wpsites_npp_navigation_links() {
    if( 'portfolio' == get_post_type() ) {?>
    <?php previous_post('&laquo; &laquo; %', 'Previous', 'no'); ?>
    | <?php next_post('% &raquo; &raquo; ', 'Next', 'no'); ?>
    } }
    add_action('genesis_after_post_content', 'wpsites_npp_navigation_links', 5 );

    • Mia
      Permalink to comment#

      Thank YOU @Brad Dalton !

      Precisely what I was in search for – I have scoured the entire WP codex / forums and – nothing !

      You ROCK \m/ ! :)

    • Brad Dalton
      Permalink to comment#

      There’s actually a better way to do this now if you’re running Genesis 2.0 HTML 5 because it adds classes for styling both previous and next post links.

      The hooks have also changed so you will need to use the 3rd parameter for positioning if running a HTML 5 enabled child theme on Genesis.

    • Mia
      Permalink to comment#

      Actually, Im not using Genesis @Brad – I simply needed to create a Next & Previous post type links without the actual text because it just didnt look good on the particular area of the page – I simply needed the left & right double angle quotes which look GREAT now :)

      I kept trying all different type of pagination functions – and all that kept occurring was that my theme kept breaking – I was about to give up until I came across your great strip of code here :)

      ( will def give you a link-back to your site once I’m done w my site )

      Thank You once again Brad :)

  31. Adam Patterson
    Permalink to comment#

    I actually wrote a plugin that “seems” to work for me.

    Let me know if you have success of fail, it should give you next / previous links inside a single custom post, I don’t think It will work in custom taxonomy but let me know :)

  32. Mrtz

    Thank you : )
    worked for me

  33. Iftekhar Bhuiyan
    Permalink to comment#

    Fantastic! it worked right away. But what about if you don’t have any post available yet? Perhaps you can use:
    if ($wp_query->have_posts()) : while ($wp_query->have_posts()) : $wp_query->the_post();
    instead of
    while ($wp_query->have_posts()) : $wp_query->the_post();
    so that we can add “else” statement to show Error message.
    This is what I am using:
    $temp = $wp_query;
    $wp_query = null;
    $wp_query = new WP_Query();
    if ($wp_query->have_posts()) : while ($wp_query->have_posts()) : $wp_query->the_post(); ?>
    <div class="entry">
    <h2 class="title"><?php the_title(); ?></h2>
    <?php the_excerpt(); ?>
    <?php endwhile; ?>
    <div class="navigation">
    <div class="alignleft"><?php next_posts_link('&laquo; Older Entries') ?></div>
    <div class="alignright"><?php previous_posts_link('Newer Entries &raquo;') ?></div>
    <?php $wp_query = null;
    $wp_query = $temp;
    <?php else : ?>
    <h2>Not Found</h2>
    <p>Sorry, but you are looking for something that isn't here.</p>
    <?php endif; ?>
    Worked like charm. Thanks.

    • Jenn
      Permalink to comment#

      This worked perfectly for me! The code Chris originally posted didn’t work for me for some reason. But this fixed it somehow so thank you so much!! I’ve been trying to solve this for days!
      Something else I learned: this won’t work if your page-slug is the same as your custom post type name. Just in case that helps others!
      Thanks again!

  34. Andy
    Permalink to comment#

    I am creating a plugin using Custom Post Types… Should Chris’s Snippet include:
    global $wp_query;
    $temp = $wp_query;

  35. Adam Patterson
    Permalink to comment#

    A lot if issues for why the pagination doesn’t work has to do with how wordpress sets it’s functions. If you don’t use the loop it seems that mist functions won’t with with custom post types.

    When I was trying to make the next post work I did not have the functions within the loop on the single template.

  36. Szyam
    Permalink to comment#

    I ended up using this:

    <?php // this is the current CPT working with NAVI!!!
    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

    $args = array('posts_per_page' => 9,'post_type' => 'reviews', 'paged' => $paged );

    $wp_query = new WP_Query($args);

    if ( $wp_query->have_posts() ) : while ( $wp_query->have_posts() ) : $wp_query->the_post();

    html here ////////////

    <?php endwhile; endif; ?>

    <?php if (function_exists('page_navi')) { // if expirimental feature is active ?>

    <?php page_navi(); // use the page navi function ?>

    <?php } else { // if it is disabled, display regular wp prev & next links ?>

    <nav class="wp-prev-next">
    <div class="page-nav">
    <div class="nav-previous"><?php next_posts_link('&lt;&lt; Next'); ?></div>
    <div class="nav-next"><?php previous_posts_link('Back &gt;&gt;'); ?></div>

    <?php } ?>


    The page_navi function is part of the 320 Foundation theme which could be omitted and just leave the “else”

  37. Mario Mc
    Permalink to comment#

    There is a easier way to paginate custom post pages without inferring with the main query :


    $paged = ( get_query_var(‘paged’)) ? get_query_var(‘paged’) : 1;
    $args = array( ‘post_type’ => ‘newsfeed’, ‘posts_per_page’ => 5, ‘paged’ => $paged );
    $newsquery = new WP_Query( $args );
    if ( $newsquery->have_posts() ) :
    while ( $newsquery->have_posts() ) : $newsquery->the_post();

    the_excerpt(); //query here

    global $newsquery; $total_pages = $newsquery->max_num_pages; if ( $total_pages > 1 ) {
    $big = 999999999; // need an unlikely integer

    echo paginate_links( array(
    ‘base’ => str_replace( $big, ‘%#%’, esc_url( get_pagenum_link( $big ) ) ),
    ‘format’ => ‘?paged=%#%’,
    ‘prev_text’ => __(‘ Prev’),
    ‘next_text’ => __(‘Next ‘),
    ‘current’ => max( 1, get_query_var(‘paged’) ),
    ‘total’ => $newsquery->max_num_pages
    ) );

    endif; wp_reset_postdata();

  38. kamran
    Permalink to comment#

    Hello Chris, first of all I am really a big fan of yours and have been following all your updates since I started the web back in 2012. Thanks for your awesome updates.

    Secondly, would you please tell me how are you achieving the syntax highlighting in your blog, I mean is there any wordpress/jquery plugin or what? I am developing my own blog and have to implement such a syntax highlighting.

    Awaiting your kind reply.

  39. Osu
    Permalink to comment#

    Is it possible to only return posts within a specific custom taxonomy? I’ve created a single-custom_post_type.php template and am using the regular wordpress loop to create my pagination for single (custom) posts, but when I try to return posts within the same taxonomy using next_post_link(), my pagination disappears. You can read more about it here:

    It seems that setting true for in_same_cat in next_post_link('format', 'link', 'in_same_cat', 'excluded_categories') doesn’t work for custom taxonomies, but is there a way to make that work?

  40. Daniel
    Permalink to comment#

    Thanks for the info!
    This wasn’t quite working for me (kept getting the 404s etc.).

    I also found this great post which shows how to add the page numbers (instead of just prev/next).

  41. Jake
    Permalink to comment#

    First, thanks for this post! Second, I got this code working on my index.php page, however, as I saw mentioned above, page 2 generates a “Page Not Found” in the title. Is there a fix for this?

  42. Mike Harding
    Permalink to comment#

    Will this work on a custom post archive template (ie. archive-artist.php) or is a custom page template (page-artists.php) required?

  43. Brad Dalton
    Permalink to comment#

    Really appreciate the link. Thanks Mia

    I’ve got over 1000 code snippets on my site i know that work because i test all of them.

    • Mia
      Permalink to comment#

      Im THERE ! soaking it all up like a sponge Obi Wan :D

      bookmarking your PastebinGithub & WP Sites

      ( between you & Chris Coyier – I could become a Rocket Scientist by this time next year ! :D )

      Thank You BOTH – its always a privilege learning from great minds :)

  44. gbarchik
    Permalink to comment#

    Hey there..
    I am using this code in my home page and when I go to page 2 (../page/2) it returns the 404 page.
    Can anyone help?

  45. Autumn
    Permalink to comment#

    I’ve been looking all over for days for code that worked for me!
    If I could even get it to paginate it was showing the same posts and I tried everything I could find.
    This worked. Thank you!

  46. Kentus_
    Permalink to comment#

    You absolute rockstar. You just saved me more hours!

    Thanks you :)

  47. Julie Clarkson
    Permalink to comment#

    Thank you Chris! Words cannot describe the magnitude of your awesomeness!

  48. Patrik
    Permalink to comment#

    There’s an issue with this method. My scenario in which this occured:
    – The blog part of the site displays 5 posts per page at most.
    – The blog has 9 posts currently.
    – My portfolio displays 2 posts per page at the most.
    – The portfolio has 8 posts currently.

    The blog thus needs two pages to display all posts, but the portfolio post type needs 4. Problem: there is no page 3 or 4. I.e. /portfolio/page/2/ works fine, but /3/ doesn’t exist. And it makes perfect sense too; WP doesn’t know what to do when it hits /3/ since the math being done would suggest that /page/2/ would be sufficient (since it is if it’s using the ‘5’ setting under “Reading”.

    Either I’ve done the implementation wrong (I’d welcome a solution…) or this method is very flawed.

    I believe this is the same problem that @gbarchik has.

  49. Samuel Guebo
    Permalink to comment#

    Thank you dude, your code works fine.

  50. Manish khatri
    Permalink to comment#

    Nice code, works perfectly. thanks for help me.

  51. Pete
    Permalink to comment#

    You have to use the var $wp_query!

    Argh! I could not understand why the posts were displayed but next_posts_link() was empty. I was using a made-up var $post_query instead of $wp_query. Know I know. And this may help someone else.

  52. Chris Montgomery
    Permalink to comment#

    showposts has been deprecated for a very long time. posts_per_page should be used instead.

  53. Nick Salloum
    Permalink to comment#

    You can improve this to a prettier numbered structure too by using WordPress’s function paginate_links. I wrote a full tutorial here on it.

  54. Sam Mathew
    Permalink to comment#

    How to filter it by taxonomi filter ?

    while ($wp_query->have_posts()) : $wp_query->the_post();
    Above code is not working at all . Please help.

  55. Rhon
    Permalink to comment#

    Thanks Man, You save the Day for this code :) … But I want to have a Numeric Pagination using the code you provide.. Is it possible?

    More Power to you Buddy :D

  56. Mobile_guy
    Permalink to comment#

    Worked like a charm. Needed the &paged=’.$paged part to complete my code.


  57. JK
    Permalink to comment#

    When I click on the “2” to go to page2 of the archive page, it goes to index.php file template. Do you know how to fix this?

    • Chris
      Permalink to comment#

      Did you solve this?
      To help others, I had the same problem for a custom post type ‘news’. I had to change my news index page URL from /news to /latest-news to solve the problem.

  58. Josie
    Permalink to comment#

    Awesome! Worked for me! Thank you so much! CSS Tricks does it again!

  59. Erez Lieberman
    Permalink to comment#

    Work Great! Thanks!

  60. Josh
    Permalink to comment#

    Thanks for this, it saved my day!

  61. Shah Alom
    Permalink to comment#

    Awesome! I was looking for this one :)

    Thank You.

  62. vitalii
    Permalink to comment#

    I use this code for WordPress custom loop with pagination:

    if ( get_query_var('paged') ) {
        $paged = get_query_var('paged');
    } elseif ( get_query_var('page') ) { // 'page' is used instead of 'paged' on Static Front Page
        $paged = get_query_var('page');
    } else {
        $paged = 1;
    $custom_query_args = array(
        'post_type' => 'post', 
        'posts_per_page' => get_option('posts_per_page'),
        'paged' => $paged,
        'post_status' => 'publish',
        'ignore_sticky_posts' => true,
        //'category_name' => 'custom-cat',
        'order' => 'DESC', // 'ASC'
        'orderby' => 'date' // modified | title | name | ID | rand
    $custom_query = new WP_Query( $custom_query_args );
    if ( $custom_query->have_posts() ) :
        while( $custom_query->have_posts() ) : $custom_query->the_post(); ?>
            <article <?php post_class(); ?>>
                <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
                <small><?php the_time('F jS, Y') ?> by <?php the_author_posts_link() ?></small>
                <div><?php the_excerpt(); ?></div>
        <?php if ($custom_query->max_num_pages > 1) : // custom pagination  ?>
            <nav class="prev-next-posts">
                <div class="prev-posts-link">
                    <?php echo get_next_posts_link( 'Older Entries', $custom_query->max_num_pages ); ?>
                <div class="next-posts-link">
                    <?php echo get_previous_posts_link( 'Newer Entries' ); ?>
        <?php endif; ?>
        wp_reset_postdata(); // reset the query 
        echo '<p>'.__('Sorry, no posts matched your criteria.').'</p>';


Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in in triple backtick fences like this:

  function example() {
    element.innerHTML = "<div>code</div>";

There's a whole bunch of content on CSS-Tricks.

Search for Stuff   •   Browse the Archives

Get the Newsletter ... or get the RSS feed