Independent Editorial DeskWordPress Releases, Builds, and Operations
Back to Archive
Implementation Notes

WordPress paginate_links Example: Build Clean Archive Pagination

Use paginate_links to build clean WordPress archive pagination with stable URLs, correct current-page state, and predictable output.

Published

April 27, 2026

Reading Time

2 min read

Updated

April 27, 2026

Archive pagination layout with stable WordPress page links and current page state.
Build PatternImplementation Notes

Implementation Notes

Extension points, code paths, and implementation choices that should survive contact with production.

Best For

WordPress developers, agencies, and technical teams building custom plugin or theme functionality with cleaner operational defaults.

Primary Topics

Implementation Notes

Editorial Focus

Build Pattern: Extension points, code paths, and implementation choices that should survive contact with production. Updated on April 27, 2026.

Full Report

Last reviewed: April 27, 2026

Archive pagination looks trivial until a theme needs accessible markup, stable URLs, or custom query arguments that survive page changes. Many WordPress sites still hand-roll page links even though paginate_links() already handles most of the hard parts.

This guide shows how to use paginate_links() for clean archive pagination with explicit base URLs, current page handling, and predictable output.

Build pagination from the current query

<?php
$current = max( 1, get_query_var( 'paged' ) );
$total   = max( 1, (int) $wp_query->max_num_pages );

$links = paginate_links(
	array(
		'base'      => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
		'format'    => '?paged=%#%',
		'current'   => $current,
		'total'     => $total,
		'mid_size'  => 1,
		'end_size'  => 1,
		'prev_text' => 'Previous',
		'next_text' => 'Next',
		'type'      => 'list',
	)
);

if ( $links ) {
	echo $links;
}

The placeholder pattern with 999999999 is standard because WordPress needs a value it can reliably replace with each page number.

Let the helper render accessible current state

paginate_links() can set the current page state automatically, including an aria-current value. That is better than manually styling one link and leaving screen readers with no context.

Use the right output type

  • plain returns a string of links.
  • array returns each link separately for custom markup control.
  • list returns a ready-made list structure that fits many themes.

For most blogs and archives, list is the best default because it is easy to style and already grouped semantically.

Preserve extra query arguments only when needed

$links = paginate_links(
	array(
		'base'     => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
		'format'   => '?paged=%#%',
		'current'  => $current,
		'total'    => $total,
		'add_args' => array(
			'sort' => 'recent',
		),
	)
);

Only carry forward arguments that are part of the real UX. Blindly forwarding everything from the request creates messy URLs fast.

Production checklist

  • Use the active query’s real current page and total page count.
  • Generate the base URL with get_pagenum_link().
  • Prefer type => 'list' for clean semantic markup.
  • Carry forward only the query arguments the UX genuinely needs.
  • Render nothing when the total page count is less than two.
  • Test pagination on archives, search results, and filtered lists separately.

Common mistakes

  • Hardcoding page URLs. Permalink structures differ between sites.
  • Using the wrong current page variable. Pagination breaks quickly on custom queries.
  • Forwarding every request argument. URLs become noisy and inconsistent.
  • Skipping empty-output checks. Single-page archives should not show pagination wrappers.
  • Building pagination manually without accessibility state. That adds work for worse output.

Related reading

If the archive query itself is customized, pair this with the pre_get_posts guide. If the page layout differs by archive type, combine it with the template hierarchy article.

References and further reading

Popular Guides

Popular WordPress guides to read next.

These articles connect recurring production concerns: implementation details, updates, troubleshooting, recovery paths, and operational cleanup.

Continue Reading

More from the archive.

Diagnostic dashboard scene representing a WordPress Site Health review before major updates.
01Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Site Health Check Before Major Updates: What to Review First

A pre-update WordPress Site Health checklist covering loopbacks, connectivity, debug settings, and environment readiness.

Structured data and route review scene representing permalink validation after a WordPress migration.
02Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Permalink Checklist After Migration: Catch URL Problems Early

A post-migration WordPress permalink checklist for checking rewrite rules, post URLs, archives, and redirect noise.

Technical media workspace representing image preparation and optimization before upload to WordPress.
03Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Image Optimization Checklist: What to Fix Before Upload

A practical WordPress image optimization checklist covering dimensions, compression, formats, and Media settings before upload.