Darren Bachan Darren Bachan - 6 months ago 113
HTML Question

How can I wrap page numbers from the_posts_pagination in WordPress into my own div?

In WordPress, I'm using

the_posts_pagination
to spit out prev/next buttons and page numbers in between. I don't like how WordPress spits out its own markup when I'd like to group certain elements into divs.

This is my current code:

PHP

<?php the_posts_pagination( array(
'mid_size' => 2,
'prev_text' => __( 'Previous Page', 'textdomain' ),
'next_text' => __( 'Next Page', 'textdomain' ),
'screen_reader_text' => ( '' )
) ); ?>


It spits out this:

HTML

<nav class="navigation pagination" role="navigation">
<div class="nav-links">
<a class="prev page-numbers" href="#">Prev Page</a>
<a class="page-numbers" href="#">1</a>
<span class="page-numbers current">2</span>
<a class="page-numbers" href="">3</a>
<a class="page-numbers" href="">4</a>
<a class="next page-numbers" href="">Next Page</a>
</div>
</nav>


I'd like the ability to make it look like this:

<nav class="navigation pagination" role="navigation">
<div class="nav-links">
<a class="prev page-numbers" href="#">Prev Page</a>
<div class="page-numbers-container">
<a class="page-numbers" href="#">1</a>
<span class="page-numbers current">2</span>
<a class="page-numbers" href="">3</a>
<a class="page-numbers" href="">4</a>
</div>
<a class="next page-numbers" href="">Next Page</a>
</div>
</nav>


Even if I could wrap the next and previous links in a div that'd be great too. I don't want to have to edit anything from the core WordPress files. Would I need to write a function?

EDIT

This is in my index.php

<?php the_posts_pagination( wp_custom_pagination(['prev_text' => __( 'Previous Page', 'textdomain' ), 'next_text' => __( 'Next Page', 'textdomain' )])); ?>


This is what I put inside the 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">
<h2 class="screen-reader-text">%2$s</h2>
<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);

}

Dan Dan
Answer

the_posts_pagination() uses paginate_links() which has no filter to alter the output as you want.

So, let's create a custom pagination template:

function the_so37580965_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( 'the_so37580965_navigation_markup_template', '
    <nav class="navigation %1$s" role="navigation">
        <h2 class="screen-reader-text">%2$s</h2>
        <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);

}

Try it out. Also, take a look at paginate_links() function, there're many more arguments you may need.

Comments