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:
- Go to Appearance > Editor.
- Open the template you want to edit (e.g., Home or Archive).
- Add the Query Loop block.
- 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.