How to Add a ‘Posts Per Page’ Option to WordPress Pagination

Standard WordPress pagination is often limited to a fixed number of posts set in the reading settings. However, providing users with the flexibility to choose their preferred layout—such as 12, 18, or 24 items per page—can significantly improve the browsing experience on content-heavy sites. In this tutorial, we’ll implement a custom “Posts Per Page” selector using a combination of HTML, JavaScript, and the pre_get_posts hook.

Step 1: Create the Selector UI

First, we need to add a simple dropdown menu to our archive or blog template. This form uses the GET method so the preference is stored in the URL, making it shareable and SEO-friendly.

<?php 
// Define the available options
$options = [get_option('posts_per_page'), 12, 18, 24]; 
?>

<form id="wprs-pager-form" class="flex items-center" action="" method="get">
    <label for="wprs-cpg" class="whitespace-nowrap mr-2">Show:</label>
    <select name="cpg" id="wprs-cpg" class="border rounded px-2 py-1">
        <?php foreach ($options as $option): ?>
            <option value="<?= $option; ?>" <?= (isset($_GET['cpg']) && $_GET['cpg'] == $option) ? 'selected' : ''; ?>>
                <?= $option; ?>
            </option>
        <?php endforeach; ?>
    </select>
    <span class="ml-2">per page</span>
</form>

To make it even more user-friendly, we’ll add a tiny bit of jQuery to automatically submit the form whenever the selection changes.

jQuery(document).ready(function($) {
    $('#wprs-cpg').on('change', function() {
        $('#wprs-pager-form').submit();
    });
});

Step 2: Modify the WordPress Query

Finally, we need to tell WordPress to respect this new parameter. We’ll use the pre_get_posts hook to check for the cpg variable in the URL and update the main query accordingly before the posts are fetched from the database.

add_action('pre_get_posts', function ($query) {
    // Only target the main query on front-end pages
    if ( ! is_admin() && $query->is_main_query() && isset($_GET['cpg']) ) {
        $posts_per_page = intval($_GET['cpg']);
        
        // Ensure we only accept valid numbers to prevent abuse
        if ( in_array($posts_per_page, [12, 18, 24, get_option('posts_per_page')]) ) {
            $query->set('posts_per_page', $posts_per_page);
        }
    }
});

By following these steps, you’ve added a professional touch to your WordPress site that empowers your visitors to customize their viewing experience. This same logic can be extended to implement custom sorting (e.g., by date or title) or view switching (grid vs. list).

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *