It is no secret that I try to advocate the use of core functions when possible. The idea of maintaining less code is a great one for any developer. It’s the old set it and forget mentality.

What I do see a lot of is the use of my_theme_pagination that uses get_pagenum_link in order to get all the page links. Yes it does use a core function but it uses it several times. Why not just use a core function that has been available since 2.1? Talk about way back, right? The best part is that you are given a few options when you use paginate_links.

The core code

Let us take a look at the core code. The function is found in the general-template.php file of the wp-includes folder. There are approximately 142 lines that make up this function. As you can see there is quite a bit of logic behind it to work. We will look at the key things. The first one being the array we can pass as an argument, and the second being the type key in that array.

You can use the function without passing anything to it and it will work. There is a reason for that. The $args parameter that can be passed gets merged with a few defaults. What are those, you ask? Here they are:

$defaults = array(
	'base' => $pagenum_link, // : %_% is replaced by format (below)
	'format' => $format, // ?page=%#% : %#% is replaced by the page number
	'total' => $total,
	'current' => $current,
	'show_all' => false,
	'prev_next' => true,
	'prev_text' => __('« Previous'),
	'next_text' => __('Next »'),
	'end_size' => 1,
	'mid_size' => 2,
	'type' => 'plain',
	'add_args' => array(), // array of query args to add
	'add_fragment' => '',
	'before_page_number' => '',
	'after_page_number' => ''

$args = wp_parse_args( $args, $defaults );

Quite a few options available to use. For the sake of this post we will focus on mostly on the type. There are three possible return types. They are array,list, and an empty value. We can see those towards the end of the function:

switch ( $args['type'] ) {
	case 'array' :
		return $page_links;

	case 'list' :
		$r .= "<ul class='page-numbers'>\n\t<li>";
		$r .= join("</li>\n\t<li>", $page_links);
		$r .= "</li>\n</ul>\n";

	default :
		$r = join("\n", $page_links);

It uses a switch statement to set the $r value that is ultimately returned. Yes, paginate_links returns and does not output any content. This is where we can actually take advantage of that.


Now with that in mind let us create some example usage, yeah? This is the part that gets fun! So we will take a look at using all three options and how they can be expanded or altered to suit your theme’s needs.


Returning the array is one of the neater ways of using the function. The reason is that it returns an array of links. The amount of links is the amount of keys available for us to manipulate. Yes, we can style to our choosing. Let’s look at a sample return:

    [0] => <span class='page-numbers current'>1</span>
    [1] => <a class='page-numbers' href='https://localhost/page/2/'>2</a>
    [2] => <a class='page-numbers' href='https://localhost/page/3/'>3</a>
    [3] => <span class="page-numbers dots">&hellip;</span>
    [4] => <a class='page-numbers' href='https://localhost/page/10/'>10</a>
    [5] => <a class="next page-numbers" href="https://localhost/page/2/">Next &raquo;</a>

What’s cool about that is you can see that by default you have the CSS classes page-number, current, and dots that you can use for some styling. Pretty awesome if you ask me. You can now expand upon that markup. A good way is by using the foreach to loop over and create your HTML markup. A quick example is:

$links = paginate_links( array( 'type' => 'array' ) );

echo '<div class="pagination col-6">';
foreach( $links as $link ){
	echo $link;
echo '</div>';

Yes, that is a super quick way of doing things but you get the idea. You can expand upon that to your heart’s content and add your needed classes or markup.


Another way is returning the list. An already HTML markup of our links in an unordered list. The returning text looks a little like:

<ul class='page-numbers'>
	<li><span class='page-numbers current'>1</span></li>
	<li><a class='page-numbers' href='https://locahost/page/2/'>2</a></li>
	<li><a class='page-numbers' href='https://localhost/page/3/'>3</a></li>
	<li><span class="page-numbers dots">&hellip;</span></li>
	<li><a class='page-numbers' href='https://localhost/page/10/'>10</a></li>
	<li><a class="next page-numbers" href="https://localhost/page/2/">Next &raquo;</a></li>

What is super awesome about it is you can use just one line of code:

echo paginate_links( array( 'type' => 'list' ) );

Super awesome, right? The reason I love that is you can just leave that code and style it all. No special markup to worry about as it is already taken care of. You can use something like: {
  clear: both;
  font-size: 1.4em;
  color: #deaf01;
} li {
  display: inline-block;

It doesn’t have to be super crazy but you get the idea.

Empty value

Now for the simplest way of using the function.

echo paginate_links();

A lot of work, right? Super, super simple and you don’t have to worry about creating any extra markup. That is if you don’t want to. It returns a string of all the links and you can go about your business. If you really like super simple HTML markup then please use that.

User changes

Yes, we can have a user change a few of the things too if we want. Let’s take a quick look at how we can change the amount of links to show around the current page.

function jc_pagination(){
	echo paginate_links( 
		'show_all' => get_theme_mod( 'all-links', false ),
		'type' => 'list',
		'mid_size' => get_theme_mod( 'mid-links', 3 )

Pretty cool, right? With that get_theme_mod you can now have the user decide how many links will show before and after the current page. Yes, it is a minor touch but it can go a long way with some users.


One response to “Working with paginate_links”

  1. There’s really no good reason for most themes to call paginate_links() anymore. That’s mostly only useful for custom pagination needed by plugins.

    Instead, themes should use the core the_posts_pagination().