Simple Posts Pagination in WordPress


If ypu have been following my WordPress Tutorials, I made two posts where I discussed how you can setup a pagination that loads the data from the server using AJAX. In this tutorial we are going to focus on creating a very simple pagination without AJAX and by just relying on PHP and WordPress functions. So let’s get started!

This simple pagination includes buttons for “Next”, “Prev”, “First”, and “Last”. You can also configure how many number bullets to show on screen.

Here’s the function that will setup the posts in a paginated view:

Comments are included so read on.

      function display_posts_pagination() {
    
    global $wpdb, $post;

    // Set default variables
    $pagination_content = '';
    $current_page_url = get_permalink( $post->ID );
    $page_number = isset( $_GET[ 'pageno' ] ) ? $_GET[ 'pageno' ] : 1;
    
    // Sanitize the received page   
    $page = sanitize_text_field( $page_number );
    $cur_page = $page;
    $page -= 1;
    // Set the number of results to display
    $per_page = 5;
    $previous_btn = true;
    $next_btn = true;
    $first_btn = true;
    $last_btn = true;
    $start = $page * $per_page;

    // Set the table where we will be querying data
    $table_name = $wpdb->prefix . 'posts';

    // Query the necessary posts
    $all_blog_posts = $wpdb->get_results( $wpdb->prepare( '
            SELECT * FROM ' . $table_name . ' WHERE post_type = "post" AND post_status = "publish" ORDER BY post_date DESC LIMIT %d, %d', $start, $per_page ) );

    // At the same time, count the number of queried posts
    $count = $wpdb->get_var( $wpdb->prepare( '
            SELECT COUNT(ID) FROM ' . $table_name . ' WHERE post_type = "post" AND post_status = "publish"', array() ) );

    /**
     * Use WP_Query:
     *
      $all_blog_posts = new WP_Query(
      array(
      'post_type'         => 'post',
      'post_status '      => 'publish',
      'orderby'           => 'post_date',
      'order'             => 'DESC',
      'posts_per_page'    => $per_page,
      'offset'            => $start
      )
      );

      $count = new WP_Query(
      array(
      'post_type'         => 'post',
      'post_status '      => 'publish',
      'posts_per_page'    => -1
      )
      );
     */
     
    // Loop into all the posts
    foreach ( $all_blog_posts as $key => $post ):

        // Set the desired output into a variable
        $pagination_content .= '
            <div class = "col-md-12">       
                <h2><a href="' . get_permalink( $post->ID ) . '">' . $post->post_title . '</a></h2>
                <p>' . $post->post_excerpt . '</p>
            </div>';

    endforeach;

    // Optional, wrap the output into a container
    $pagination_content = '<div class="cvf-universal-content">' . $pagination_content . '</div><br class = "clear" />';

    // This is where the magic happens
    $no_of_paginations = ceil( $count / $per_page );

    if ( $cur_page >= 7 ) {
        $start_loop = $cur_page - 3;
        if ( $no_of_paginations > $cur_page + 3 )
            $end_loop = $cur_page + 3;
        else if ( $cur_page <= $no_of_paginations && $cur_page > $no_of_paginations - 6 ) {
            $start_loop = $no_of_paginations - 6;
            $end_loop = $no_of_paginations;
        } else {
            $end_loop = $no_of_paginations;
        }
    } else {
        $start_loop = 1;
        if ( $no_of_paginations > 7 )
            $end_loop = 7;
        else
            $end_loop = $no_of_paginations;
    }

    // Pagination Buttons logic     
    $pagination_nav .= '
        <div class="pagination-container">
            <ul>';

    if ( $first_btn && $cur_page > 1 ) {
        $pagination_nav .= '<li class="active"><a href = "' . $current_page_url . '?pageno=1">First</a></li>';
    } else if ( $first_btn ) {
        $pagination_nav .= '<li class="inactive">First</li>';
    }

    if ( $previous_btn && $cur_page > 1 ) {
        $pre = $cur_page - 1;
        $pagination_nav .= '<li class="active"><a href = "' . $current_page_url . '?pageno=' . $pre . '">Previous</a></li>';
    } else if ( $previous_btn ) {
        $pagination_nav .= '<li class="inactive">Previous</li>';
    }
    for ( $i = $start_loop; $i <= $end_loop; $i ++  ) {

        if ( $cur_page == $i )
            $pagination_nav .= '<li class = "selected">' . $i . '</li>';
        else
            $pagination_nav .= '<li class="active"><a href = "' . $current_page_url . '?pageno=' . $i . '">' . $i . '</a></li>';
    }

    if ( $next_btn && $cur_page < $no_of_paginations ) {
        $nex = $cur_page + 1;
        $pagination_nav .= '<li class="active"><a href = "' . $current_page_url . '?pageno=' . $nex . '">Next</a></li>';
    } else if ( $next_btn ) {
        $pagination_nav .= '<li class="inactive">Next</li>';
    }

    if ( $last_btn && $cur_page < $no_of_paginations ) {
        $pagination_nav .= '<li class="active"><a href = "' . $current_page_url . '?pageno=' . $no_of_paginations . '">Last</a></li>';
    } else if ( $last_btn ) {
        $pagination_nav .= '<li class="inactive">Last</li>';
    }

    $pagination_nav = $pagination_nav . '
            </ul>
        </div>';
    
    $output = '
        <div>' . $pagination_content . '</div>
        <div>' . $pagination_nav . '</div>
    ';
    
    return $output;
}

The function does not accept any parameters, but feel free to add some as you wish!

Styling

Here’s a ready made style for your navigation buttons:

.pagination-container  { margin-top: 15px; }
.pagination-container ul { margin: 0; padding: 0; }
.pagination-container ul li { display: inline; background: #FFF; color: black; }
.pagination-container ul li.active a:hover { background: #1E8CBE; color: white; text-decoration: none; }
.pagination-container ul li.inactive { background: #7E7E7E; }
.pagination-container ul li.selected { background: #1E8CBE; color: white; }
.pagination-container ul li a, .pagination-container ul li.inactive, .pagination-container ul li.selected { margin: 3px; padding: 4px 8px; }






Related Post


Latest Post


Recent Posts Widget

Make sure to never miss a thing...

Get the latest news from the creative industry along with other creative goodies, conveniently delivered to social media.