Add proper pagination as default

Add proper pagination as default

Online by JSC0d3
May 23, 2017 | | 281 recognitions

When you scroll to the bottom of an index page on a WordPress site, what do you see? Chances are it’s two links, one saying “Older Posts” and one saying “Newer Posts”. Scarcely has any default setting been more engagingly uninformative, and unnecessarily so. This “let’s not tell the visitor where she is on the site nor how much other content is available” approach to navigation is the epitome of User Experience archaism and should be but a footnote in the annals of WordPress history. Instead it is a cornerstone of the free WordPress theme experience and the default setting for all baseline WordPress themes (_s included) with one groundbreaking exception: Twenty Fourteen.

It is time we the people who build WordPress themes cast aside the rotting corpse of Older and Newer posts and replace it with proper pagination. After all the function is already built into WordPress – in fact it has been for a very, very long time. So, without further ado let me provide you with the code you need to get started and a few tweaks to move your WordPress pagination into the 21st century.

paginate_links() – the old friend you never knew

The paginate_links() function will do that for you in a snap. Here it is in its most basic form, straight from the Codex:

global $wp_query; $big = 999999999; // need an unlikely integer
echo paginate_links( array( 
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 
'format' => '?paged=%#%', 
'current' => max( 1, get_query_var('paged') ),
'total' => $wp_query->max_num_pages ) );

(If you’re wondering what the $big variable is for it helps output a clean URL when the page is loaded.)

Slot this code into your template file where you want the pagination to appear (i.e. replace the current Older Posts and Newer Posts code with this one) and you’re good to go. If you want the basic solution that is. Which probably isn’t what you want.
Options Aplenty

Luckily for us we don’t have to be content with the default example above. paginate_links() has plenty of parameters we can use to change its output. The parameters you should care about from a design perspective are:

  1. end_size: Decides how many numbers to display at the start and end of the list. Defaults to 1 meaning you’ll get output like this: 2 … 5 6 7 … 10. If you change the number to 2 you’ll get 2 3 … 5 6 7 … 9 10. You get the idea. Visually 1 looks best but in some cases you may want to change this value.
  2. mid_size: Decides how many numbers to display on the left and right side of the current page (not including the current page). Defaults to 1. So if you set mid_size to 2 and are on page 6 you’d get 2 … 4 5 6 7 8 … 10.
  3. prev_next: True or false decides whether a Previous and Next link should appear in the list or not. The actual wording is controlled separately.
  4. prev_text and next_text: The actual text output displayed if prev_next is set to true. Default output is « Previous and Next » and the strings are wrapped and prepared for translation.
  5. type: Decides what the function outputs. The default plain outputs a list of anchor tags (links) which imo makes no sense. This can be switched to either array (great if you want complete control and know how to handle arrays in PHP) or list which outputs an unordered list and should be the default setting. I strongly recommend setting type to list so you can work with the output in a reasonable way.

So, let’s say you want to add pagination to your site (not unlike what you see directly above here) and you want to do it in a clean way. In that case it behooves you to create a function, stash it in functions.php or template-tags.php in your theme or child theme, and call it in when necessary. The easiest way to get this working, and working properly, is to upcycle the function provided in Twenty Fourteen and make some subtle changes to its output:

if ( ! function_exists( 'mytheme_paging_nav' ) ) :
 * Display navigation to next/previous set of posts when applicable.
 * Based on paging nav function from Twenty Fourteen

function mytheme_paging_nav() {
	// Don't print empty markup if there's only one page.
	if ( $GLOBALS['wp_query']->max_num_pages < 2 ) {

	$paged        = get_query_var( 'paged' ) ? intval( get_query_var( 'paged' ) ) : 1;
	$pagenum_link = html_entity_decode( get_pagenum_link() );
	$query_args   = array();
	$url_parts    = explode( '?', $pagenum_link );

	if ( isset( $url_parts[1] ) ) {
		wp_parse_str( $url_parts[1], $query_args );

	$pagenum_link = remove_query_arg( array_keys( $query_args ), $pagenum_link );
	$pagenum_link = trailingslashit( $pagenum_link ) . '%_%';

	$format  = $GLOBALS['wp_rewrite']->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
	$format .= $GLOBALS['wp_rewrite']->using_permalinks() ? user_trailingslashit( 'page/%#%', 'paged' ) : '?paged=%#%';

	// Set up paginated links.
	$links = paginate_links( array(
		'base'     => $pagenum_link,
		'format'   => $format,
		'total'    => $GLOBALS['wp_query']->max_num_pages,
		'current'  => $paged,
		'mid_size' => 3,
		'add_args' => array_map( 'urlencode', $query_args ),
		'prev_text' => __( '&larr; Previous', 'mytheme' ),
		'next_text' => __( 'Next &rarr;', 'mytheme' ),
		'type'      => 'list',
	) );

	if ( $links ) :

	?> <nav class="navigation paging-navigation" role="navigation"> <h1 class="screen-reader-text"><?php _e( 'Posts navigation', 'mytheme' ); ?></h1> <?php echo $links; ?> </nav><!-- .navigation --> <?php

To make this work in a template simply call the function like this:


The function will output clean HTML markup with the pagination links wrapped in list items within an unordered list.Now all you need is some basic CSS to make it all look good.

JSC0d3's Logo
About JSC0d3

JSC0d3 is an entrepreneur, online marketer, and an employee of an IT company. When not building websites, creating content, or helping customers improve their online business, spend time with their wife and two beautiful children. Although he still feels new in WordPress, he enjoys sharing what he has learned with all of you! If you want to get in touch with him, you can do this through this website.

On the same idea

Posted by | April 1, 2019

Images are vital components of every website Before you start questioning the importance of images, just try to imagine your favorite blog or website...

Posted by | March 5, 2019

I’ve been loosely following the noise and #wpdrama surrounding Gutenberg for as long as it has been around and honestly for the most part I’ve...

Posted by | February 24, 2019

To ensure that your site ranks highly in Search Engine Result Pages (SERPs), you’ll need to make it easy for search engine ‘bots’ to explore...

Previous PostBackNext Post

Leave here an impression