If you are looking for a way to add numbered pagination to your WordPress theme instead of the default “Next Posts” and “Previous Posts,” you can easily do this using the plugin most of you probably know, called WP-PageNavi.
Personally, I prefer to add pagination manually to the themes I build to avoid using a plugin, as it helps maintain the speed of these themes and saves unnecessary use of CSS and JavaScript files.
There is a function I noticed not many are familiar with, called paginate_links, which was added to WordPress in version 2.1. This function allows you to create numbered pagination for any query in your WordPress theme.
By default, the function comes with the following settings:
<?php $args = array(
'base' => '%_%',
'format' => '?page=%#%', // the '%#%' will be replaced with the page number
'total' => 1,
'current' => 0,
'show_all' => False,
'end_size' => 1,
'mid_size' => 2,
'prev_next' => True,
'prev_text' => __('« Previous'),
'next_text' => __('Next »'),
'type' => 'plain',
'add_args' => False,
'add_fragment' => '',
'before_page_number' => '',
'after_page_number' => ''
); ?>
We won’t go into detail about these settings, but check out the WordPress Codex to learn more about all the parameters of the paginate_links()
function. Here’s a quick guide on how to add numbered pagination to your WordPress theme, just like in this blog.
It’s worth mentioning that you can forgo traditional pagination and add the infinite scroll option or alternatively, the option to load more posts via a button.
Adding Pagination to a WordPress Theme
Add the following code to your theme’s functions.php
file (or any other file you find appropriate in your theme):
/**
* Pagination for archive, taxonomy, category, tag and search results pages
*
* @global $wp_query http://codex.wordpress.org/Class_Reference/WP_Query
* @return Prints the HTML for the pagination if a template is $paged
*/
function sv_pagination() {
global $wp_query;
$next_arrow = is_rtl() ? esc_html( '<' ) : esc_html( '>' );
$prev_arrow = is_rtl() ? esc_html( '>' ) : esc_html( '<' );
$total = $wp_query->max_num_pages;
$big = 999999999; // This needs to be an unlikely integer
// For more options and info view the docs for paginate_links()
// http://codex.wordpress.org/Function_Reference/paginate_links
$paginate_links = paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link($big) ) ),
'current' => max( 1, get_query_var('paged') ),
'total' => $total,
'show_all' => true,
'prev_text' => $prev_arrow,
'next_text' => $next_arrow
) );
// Display the pagination if more than one page is found
if ( $paginate_links ) {
echo '<div class="pagination">';
echo $paginate_links;
echo '</div>';
}
}
We’ve set a few basic parameters for the paginate_links
function, and to be honest, I haven’t gone through all of them. However, it’s important to note—if you want to make the pagination accessible (and you should), add the following variable at the beginning of the function:
$translated = __( 'Page', 'mytextdomain' );
Then, add the following parameter to the paginate_links
array in the above code:
'before_page_number' => '<span class="accessible-txt">'.$translated.' </span>'
You might want to hide the
accessible-txt
class in your CSS file…
Styling the Pagination
We’ll use Flexbox to make things easier. To style the numbered pagination like this blog, add the following code to your child theme’s style.css
file:
.pagination {
display: flex;
-webkit-box-pack: justify;
-moz-box-pack: justify;
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
flex-flow: row wrap;
}
.pagination > * {
color: #2d2d2d;
border-radius: 50%;
text-align: center;
-webkit-flex-basis: 36px; /* Safari 6.1+ */
flex-basis: 36px;
line-height: 36px;
min-width: 36px;
margin: 4px 0;
}
.pagination > * {
color: #2d2d2d;
border-radius: 50%;
text-align: center;
background: #f3f3ef;
}
.pagination > a:hover, span.current {
background-color: #942762;
color: #fefefe;
}
Adding Pagination to Your Theme
It’s very simple. To call the pagination function in your theme, just add the following line of code where you want the pagination to appear. Typically, you’ll add this code to index.php
, category.php
, archive.php
, and similar files, but if you have a custom page template, add it there:
<?php sv_pagination(); ?>
If you’re using a template file or page that already has the default WordPress pagination, replace it with this code.
Custom Query Loop?
If you are using a custom loop with WP_Query, the code won’t work unless you assign your query
to the $wp_query
variable (don’t do this). To fix this, when I create a custom loop, it usually looks like this:
$sv_query = new WP_Query( $args );
This way, we can modify the pagination function to check if you used this variable to create the loop, and adjust the $total
variable accordingly (update the first code snippet in this post):
global $wp_query, $sv_query;
if ( $sv_query ) {
$total = $sv_query->max_num_pages;
}
else {
$total = $wp_query->max_num_pages;
}
Your custom loop should basically look like the following:
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
'post_type' => 'post', // You can add a custom post type if you like
'posts_per_page' => 6,
'paged' => $paged
);
$sv_query = new WP_Query( $args );
if ( $sv_query->have_posts() ) : while ( $sv_query->have_posts() ) : $sv_query->the_post();
//*** Post content goes here
endwhile;
sv_pagination();
wp_reset_postdata();
else :
//*** If no posts found message goes here
endif;
?>
Note that on line 17, after completing the loop, we used the wp_reset_postdata()
function to restore the global $post
variable after using the new loop created with WP_Query
.
Conclusion
Using numbered pagination provides a simple and clear way to navigate through your blog. It helps users easily understand how many pages and posts your site has while providing a better user experience.
With just a few lines of PHP and CSS, you can easily add beautiful pagination to your WordPress blog. Learn more about pagination and the rel=next and rel=prev tags in this post.
Does it work for you? Got improvement ideas? Share with us in the comments so we can all learn… 🙂