I have custom pagination that allows me to modify the mark-up for the code WP outputs:

in functions.php

function wp_custom_pagination($args = [], $class = 'pagination') {

            if ($GLOBALS['wp_query']->max_num_pages <= 1) return;

            $args = wp_parse_args( $args, [
                'mid_size'           => 2,
                'prev_next'          => false,
                'prev_text'          => __('Older posts', 'textdomain'),
                'next_text'          => __('Newer posts', 'textdomain'),
                'screen_reader_text' => __('Posts navigation', 'textdomain'),

            $links     = paginate_links($args);
            $next_link = get_previous_posts_link($args['next_text']);
            $prev_link = get_next_posts_link($args['prev_text']);
            $template  = apply_filters( 'navigation_markup_template', '
            <nav class="navigation %1$s" role="navigation">
                <div class="nav-links">%3$s<div class="page-numbers-container">%4$s</div>%5$s</div>
            </nav>', $args, $class);

            echo sprintf($template, $class, $args['screen_reader_text'], $prev_link, $links, $next_link);

        add_filter('previous_posts_link_attributes', function() 
        return 'class="next"'; 

        add_filter('next_posts_link_attributes', function() 
        return 'class="prev"'; 

This is how I call it in my template files:

<?php wp_custom_pagination([
   'prev_text' => __( '<i class="fa fa-long-arrow-left"></i> Prev Page', 'textdomain' ), 
   'next_text' => __( 'Next Page <i class="fa fa-long-arrow-right"></i>', 'textdomain' )

Now, this works, for the most part, but I have a live example where I set it so I can only see 1 post per page for testing purposes. The pagination creates too many numbers, which breaks my styling, but that's more CSS, I am thinking of a solution. Can I make it look like this?:


[1]...[4] [5] [6]...[9]


1 Answer 1


'mid_size' => 2, controls how many numbers are shown each side of the current page. Currently you have it set to 2, which means you'll get 5 numbers (current and 2 each side).. except on the first and last page where you get 2 on one side but there are no numbers to show on the other side.

You can dynamically set the mid_size based on which page you are currently on:

global $wp_query;

$mid_size = 1; // default to 1 number each side

// Check if we are on the first or last page
$current_page = get_query_var('paged');
if ( !$current_page || $current_page == $wp_query->max_num_pages ) {
    $mid_size = 2; // 2 numbers before/after the current page

$args = wp_parse_args( $args, [
    'mid_size' => $mid_size,
    //... rest of code

All you do is check the paged query var, if it isn't set you're on the first page, if it equals the total number of pages you're on the last page.

If you're on page 3 or 2 pages from the last page you will have 1 number on one side and 2 on the other since the first and last page isn't included in the 'mid_size', but I'm not sure there is a way to easily prevent that as you can't control the start and end numbers independently.

I also just noticed that your previous/next posts links are the wrong way round (check your live example). They work opposite to how you would expect. If you read the docs, they say:

Because post queries are usually sorted in reverse chronological order, next_posts_link() usually points to older entries (toward the end of the set) and previous_posts_link() usually points to newer entries (toward the beginning of the set).

  • I changed it the mid_size to 1 and it fits nicely. The dots on the left hand side work too, beautiful. Thanks! Jun 12, 2016 at 2:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.