How to Add WordPress Pagination Without Plugins?


Introduction: Why Add Pagination Without Plugins?

If you’re building a WordPress site, you’ve probably run into that annoying endless scrolling of posts on your blog page. That’s where pagination steps in. It breaks your content into neat, manageable pages. Now, sure, there are plugins galore that handle this for you—but here’s the catch: they often bring in unnecessary code, slow down your site, and mess with your SEO. Why rely on plugins when you can do it with a few lines of code?

Pagination without plugins gives you full control over how your pages look and perform. It keeps things lightweight and custom. Plus, you’re not at the mercy of a plugin developer’s updates or bugs. Whether you’re a developer or just a DIY site owner, learning how to add pagination manually is a skill worth mastering.

So, let’s dive in and see exactly how you can build a clean, efficient, and SEO-friendly pagination system directly within your WordPress theme—without touching a plugin.


Understanding the WordPress Loop

Before adding pagination, it’s crucial to understand the WordPress loop. This is the heartbeat of any WordPress site. It’s how WordPress fetches posts from the database and displays them on your site. The loop is usually found in template files like index.php, home.php, or archive.php.

A basic WordPress loop looks something like this:

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<!-- Post content goes here -->
<?php endwhile; endif; ?>

When you add pagination, you’re essentially telling WordPress: “Hey, don’t show all posts at once—split them into pages.”

The loop must be compatible with pagination functions like paginate_links() or the_posts_pagination() for things to work smoothly. Also, if you’re using a custom query (like with WP_Query), you’ll need to pass the right parameters like paged and posts_per_page to make pagination work.

Knowing where your loop lives and how it functions is the first major step in this pagination journey.


The Downsides of Plugin-Based Pagination

Let’s be real—plugins make WordPress easy. But when it comes to pagination, plugins are often overkill. Here’s why:

1Performance Issues

Most pagination plugins load their own scripts, styles, and jQuery libraries, adding unnecessary weight to your site. That means longer load times, especially on mobile devices.

SEO Conflicts

Some pagination plugins don’t handle SEO correctly. They might create duplicate content or generate URLs that search engines struggle to crawl. A poorly coded plugin can easily break your SEO structure.

Lack of Flexibility

Want to change how the pagination looks? Tough luck. Most plugins only offer basic styling options unless you dig into the plugin’s code, which defeats the purpose of using it in the first place.

Plugin Updates and Conflicts

A plugin might work today and crash tomorrow after a WordPress update. Or it might clash with your theme or another plugin. And don’t get started on abandoned plugins—those are a ticking time bomb.

You Can Do It with 10 Lines of Code

Yes, really. A few lines in your theme’s template and a touch of CSS can give you fast, responsive, and attractive pagination—without compromising performance or SEO.


Pre-Requisites: Things You Need Before Adding Pagination

Before jumping into code, it’s good to get prepared. Don’t worry—it’s nothing too technical, but these steps can save your site from unexpected errors:

1. Access to Your Theme Files

You’ll need access to your theme’s files, especially index.php, archive.php, and possibly functions.php. Use an FTP client like FileZilla or your hosting control panel’s file manager.

2. Use a Child Theme

Never modify the core theme directly. Use a child theme instead. This keeps your customizations safe when the main theme updates.

3. Backup Your Site

Always, always, always back up your site before making changes. Use a plugin like UpdraftPlus or a manual backup method.

4. Code Editor

Use a proper code editor like VS Code or Sublime Text. Don’t edit theme files through the WordPress admin unless you’re absolutely sure what you’re doing.

5. Basic Knowledge of PHP

You don’t need to be a developer, but understanding basic PHP will help you avoid syntax errors and debug issues quickly.

Once you’ve got all this in place, you’re ready to rock. Let’s move on to the fun part—coding!


How to Add WordPress Pagination Without Plugins (Step-by-Step)

Let’s walk through how to manually add pagination in your WordPress theme. This is where the magic begins.

Step 1: Open the Correct Template File

Start with index.php, archive.php, or home.php. These are typically the templates where your posts are listed.

Step 2: Replace or Modify the Loop

Make sure your loop is inside a while(have_posts()) : the_post() structure.

Step 3: Add Pagination Code

Below your loop (after endwhile), add the following code:

<?php
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
) );
?>

This code uses the built-in paginate_links() function to generate page links. It works with your theme’s pagination structure and doesn’t rely on any external plugin.

Step 4: Save and Test

Upload the file, refresh your site, and boom—pagination appears like magic. You’ll likely need to style it, but functionally, it should be working now.


Creating Custom Pagination Function

Want cleaner code and reusable pagination across multiple templates? The best way to do that is by creating a custom pagination function in your functions.php file. This not only keeps your template files neat but also centralizes control in case you want to modify or enhance the pagination later.

Step 1: Open functions.php

Navigate to your theme’s functions.php file. Always do this in a child theme to prevent losing your customizations during theme updates.

Step 2: Add the Custom Function

Paste the following function into your functions.php file:

function custom_pagination() {
global $wp_query;
$big = 999999999; // need an unlikely integer

$pages = 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,
'type' => 'array',
'prev_text' => __('« Prev'),
'next_text' => __('Next »'),
) );

if( is_array( $pages ) ) {
echo '<ul class="pagination">';
foreach ( $pages as $page ) {
echo "<li>$page</li>";
}
echo '</ul>';
}
}

This function outputs pagination in an unordered list, which is easier to style using CSS. You can now reuse this function wherever you want pagination to appear.

Step 3: Call the Function in Your Template

Replace the pagination code in your template file with:

<?php custom_pagination(); ?>

Now your templates are cleaner, and pagination logic is handled entirely from one place.


Styling Your Pagination with CSS

Even though your pagination works now, it probably looks pretty bland. Time to dress it up a bit!

Here’s a simple CSS snippet you can use to style your pagination links. Add this to your theme’s style.css file:

.pagination {
list-style: none;
display: flex;
justify-content: center;
padding: 0;
margin: 30px 0;
}

.pagination li {
margin: 0 5px;
}

.pagination li a,
.pagination li span {
padding: 10px 15px;
border: 1px solid #ddd;
color: #333;
text-decoration: none;
transition: all 0.3s;
display: block;
}

.pagination li a:hover {
background-color: #0073aa;
color: #fff;
border-color: #0073aa;
}

.pagination li .current {
background-color: #0073aa;
color: #fff;
border-color: #0073aa;
}

Responsive Styling Tips:

  • Use flex-wrap: wrap; in .pagination for better mobile display.
  • Use @media queries to adjust padding or font-size on smaller screens.

This styling gives you neat, clickable page numbers that fit right into most themes without breaking design consistency.


Improving SEO with Pagination

Pagination isn’t just about user experience—it plays a big role in SEO too. If done wrong, it can cause crawl issues or duplicate content. Done right, it enhances your site’s structure.

Use rel=prev and rel=next

Google used to recommend these tags, but even though they’re no longer officially used, they still help with structure:

<link rel="prev" href="http://example.com/page/1" />
<link rel="next" href="http://example.com/page/3" />

You can add this manually in the <head> section of your theme using a filter in functions.php.

Avoid Duplicate Content

Make sure paginated pages use canonical tags pointing to themselves. WordPress handles this by default, but custom setups might need adjustments.

Noindex Certain Pages?

In some setups, it’s smart to noindex paginated pages, especially when they dilute content. However, this depends on your SEO goals and site structure. Use Yoast or Rank Math to control indexation easily.

Use Descriptive Page Titles

Instead of generic “Page 2,” use titles like:

How to Add WordPress Pagination Without Plugins – Page 2 of 5

This helps both users and search engines understand what the page contains.


Using functions.php to Simplify Pagination

To streamline pagination across multiple template files, you can extend your earlier custom function or modularize more features.

Add Arguments to Your Function

Allow your pagination function to accept arguments, making it more versatile:

function custom_pagination_v2($query = null) {
if (!$query) {
global $wp_query;
$query = $wp_query;
}

$big = 999999999;
$pages = paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $query->max_num_pages,
'type' => 'array',
'prev_text' => __('« Previous'),
'next_text' => __('Next »'),
) );

if( is_array( $pages ) ) {
echo '<ul class="pagination">';
foreach ( $pages as $page ) {
echo "<li>$page</li>";
}
echo '</ul>';
}
}

Now, you can pass custom queries if needed:

custom_pagination_v2($custom_query);

Use Hooks for Auto Pagination

If you always want pagination to appear after posts, you can hook it:

add_action('loop_end', 'custom_pagination');

This adds pagination after every standard loop, making your code even more hands-free.


Adding Pagination to Custom Post Types

If you’re using custom post types (CPTs), you need to make sure the pagination works with custom loops.

Here’s how:

Custom Query Example:

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'portfolio',
'posts_per_page' => 6,
'paged' => $paged
);
$custom_query = new WP_Query($args);

if ($custom_query->have_posts()) :
while ($custom_query->have_posts()) : $custom_query->the_post();
// Your loop code
endwhile;

custom_pagination_v2($custom_query);
wp_reset_postdata();
endif;

This code handles pagination beautifully for CPTs like “portfolio”, “projects”, or “events”. Just make sure paged is set correctly, and you’re good to go.


Pagination for Category, Tag, and Search Pages

Pagination isn’t just for your main blog page—it’s just as useful on category, tag, and search result pages. These templates usually include their own version of the loop, so let’s make sure they’re covered too.

Category & Tag Pages:

These templates are generally handled by category.php, tag.php, or the more generic archive.php. The loop here behaves similarly to the main blog loop. Simply place the pagination function after the loop.

Here’s how it might look:

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<!-- Output post content -->
<?php endwhile; ?>

<?php custom_pagination(); ?>

<?php else : ?>
<p>No posts found.</p>
<?php endif; ?>

No special modifications are needed, assuming you’re using the default query. The pagination function will automatically pick up the max_num_pages from the global $wp_query.

Search Results Pagination:

For search results, WordPress uses search.php. You’ll follow the same logic:

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<!-- Search result loop -->
<?php endwhile; ?>

<?php custom_pagination(); ?>

<?php else : ?>
<p>No results found.</p>
<?php endif; ?>

Important Tip: If you’re using a custom query in these templates (like WP_Query or query_posts()), make sure to pass the correct paged variable. Otherwise, pagination links will be generated but won’t work properly.


Troubleshooting Pagination Issues

Pagination in WordPress can sometimes be a little temperamental. If yours isn’t working right, here are some common problems and how to fix them.

1. Pagination Links Not Changing Pages

This often happens when the paged parameter is missing or incorrect in a custom query. Always define it like this:

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

Then pass it into your query:

$args = array(
'post_type' => 'post',
'paged' => $paged
);

2. 404 Errors on Page 2, 3, etc.

404 Error usually means your permalinks aren’t configured properly. Go to:

Dashboard > Settings > Permalinks
Then just click Save Changes (you don’t even have to make any changes). This flushes and resets your permalink structure.

3. Pagination Styling Is Broken

Make sure your custom CSS classes match the ones used in the pagination function. If you’re using a list (<ul> and <li>), ensure you’ve styled them properly in your theme’s CSS.

4. Multiple Loops on the Same Page

If you’re using more than one loop on a page (e.g., a featured section and then a blog list), make sure only the main loop controls the pagination—or create separate pagination for each query.

5. Pagination Doesn’t Appear at All

Check that your loop is properly closed before you add the pagination. And verify that you’re not using query_posts() incorrectly, which can overwrite the main query and break pagination.


Responsive Pagination for Mobile Users

In today’s world, more than half of web traffic comes from mobile devices. That means your pagination should look good and function well on smartphones and tablets too.

Make Pagination Touch-Friendly:

  • Use larger click areas for pagination links.
  • Avoid tiny numbers packed too closely together.

Here’s how you can adapt your CSS:

@media screen and (max-width: 768px) {
.pagination li {
margin: 3px;
}

.pagination li a,
.pagination li span {
padding: 8px 12px;
font-size: 14px;
}
}

Consider “Load More” Button for Mobile

While this isn’t classic pagination, a “Load More” button with AJAX loading is more mobile-friendly and reduces page reloads. If you’re not ready to build AJAX functionality, stick with traditional pagination and style it well.

Use SVG or Icon Arrows

Replace text-based next/previous with icons using font libraries like Font Awesome, or inline SVGs for better visuals and accessibility.

'prev_text' => '<i class="fa fa-chevron-left"></i>',
'next_text' => '<i class="fa fa-chevron-right"></i>',

Pagination in Gutenberg and Block Themes

Gutenberg block themes are the future of WordPress. If you’re using a full site editing (FSE) theme, pagination works a little differently—but not dramatically so.

Using Template Parts:

In block themes, you’ll often work with templates like home.html and archive.html. These don’t use PHP in the same way traditional themes do, but you can still add pagination by inserting the Pagination block directly inside your block templates.

To do this:

  1. Go to Appearance > Editor.
  2. Open the template you want to edit (e.g., Home or Archive).
  3. Add the Query Loop block.
  4. Inside the Query Loop, insert the Pagination block.

This gives you:

  • Previous Page
  • Next Page
  • Page Numbers

You can style these with block editor settings or custom CSS in your global styles.

PHP and Gutenberg Coexistence

You can still use traditional PHP-based pagination in hybrid themes that use Gutenberg for content but PHP for templates. In such cases, your existing paginate_links() or custom functions will still work perfectly.


Final Thoughts: Maintainable and Clean Code

Adding pagination to your WordPress site without plugins isn’t just doable—it’s smart. It gives you control, performance, and flexibility that plugins can’t always provide.

But the key to sustainable development is clean and maintainable code. Keep your custom functions organized, comment your code, and test thoroughly on different devices and pages.

If you ever decide to switch themes, having reusable pagination functions in functions.php makes migration easier. And remember, plugins aren’t evil—just don’t rely on them for something you can control better through simple code.

So go ahead—ditch the plugin bloat, and enjoy the freedom of custom-coded, optimized pagination that fits your site like a glove.


Conclusion

Adding pagination without plugins in WordPress is one of the smartest moves you can make for your website’s performance, SEO, and flexibility. Whether you’re building a theme from scratch or customizing an existing one, this guide gives you all the tools and code snippets you need to make it happen. From styling and custom post types to mobile responsiveness and Gutenberg compatibility, this approach covers all the bases.

So next time you’re tempted to hit “Install Plugin,” remember: with a few lines of code, you can build faster, smarter, and better.


FAQs

1. Can I use paginate_links() in custom queries?
Yes! Just make sure you pass the correct $custom_query->max_num_pages and paged parameter to ensure it works smoothly.

2. Why doesn’t pagination work with query_posts()?
query_posts() overrides the main query, which can cause pagination issues. It’s better to use WP_Query or modify the main query using pre_get_posts.

3. How do I remove pagination from specific pages?
Use conditional tags like is_page('about') or is_front_page() to exclude pagination in certain templates.

4. Can I customize the “Next” and “Prev” text?
Absolutely. Use 'next_text' and 'prev_text' in your paginate_links() arguments to set your own text or icons.

5. Is it better to use “Load More” or traditional pagination?
It depends. Traditional pagination is better for SEO, while “Load More” offers better UX on mobile. Choose based on your audience and site goals.

Leave a Reply

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