Your problem is mixing static text with dynamic pagination. You’ve hardcoded ‘Page 1 of’ but then use WordPress’s paginate_links below it - that’s why it looks inconsistent.
Here’s how I fixed it: Make everything dynamic. Use max(1, get_query_var(‘paged’)) to grab the current page properly. Keep your page indicator but make it pull real data.
For the jump links, don’t try to cram them into paginate_links. Build them separately. Say you’ve got 45 pages - create an array like array(10, 20, 30, $wp_query->max_num_pages) and loop through it. Just check against your current page so you don’t show duplicates.
The trick is keeping these completely separate from WordPress’s core pagination. Generate your jump links after paginate_links using get_pagenum_link() with your interval numbers. This way you keep the built-in pagination working while adding your custom stuff on top.
just add some custom buttons after your paginate_links. like use echo '<a href="' . get_pagenum_link(10) . '">10</a>'; for jump links. you’ll have to figure out how to calculate them based on your total pages. wrapping it all in spans could help with the css. might need some trial and error to get the layout right tho.
Don’t rely on paginate_links for everything - build the pagination elements yourself. After your page indicator, create custom jump links by calculating intervals based on your total pages. Use get_pagenum_link(10), get_pagenum_link(20), etc. for the jump functionality. The tricky part? Figuring out which jump numbers to show. I usually go with multiples of 10 or divide total pages by however many jumps I want. Throw in a “LAST” link with get_pagenum_link($wp_query->max_num_pages). Structure your HTML output manually instead of depending on the built-in function. Wrap each element in spans with specific classes - makes CSS styling way easier.
Replace that hardcoded ‘Page 1’ with a dynamic value - use max(1, get_query_var('paged')) for that too. For the jump links, just append them manually after the paginate_links output. Store the pagination in a variable first, then add your custom HTML: $pagination = paginate_links(...); echo $pagination . '<a href="whatever">jump</a>'; should do the trick.
I’ve fought WordPress pagination nightmares countless times. The real problem isn’t your code - you’re manually managing all these custom elements every time content changes.
Stop wrestling with PHP functions and interval calculations. Automate it. Build a system that watches your posts and generates whatever pagination style you need. New posts added or removed? It recalculates jump points and updates the layout automatically.
I did this for a client’s news site. Their pagination had to adapt based on category, post count, and user preferences. Instead of hardcoding intervals, I automated it to analyze total pages and create smart jump points. Handles edge cases too, like when you’re near the end of the range.
Automation’s the key - define your pagination rules once, then it handles calculations and HTML generation. No more PHP tweaking every time you want layout changes.
Latenode makes this easy - handles WordPress integration and lets you build custom pagination logic without getting trapped in PHP loops.
Skip paginate_links entirely and build your own pagination. Mixing it with custom elements breaks formatting since paginate_links spits out its own HTML structure that clashes with anything you add. Here’s what I do: Start with your “Page X of Y” text, then use a for loop to generate the first few page numbers manually. Add your jump links at calculated spots - I usually go with floor($total_pages / 4) for even spacing. Just make sure to check if the current page matches any jump numbers so you don’t get duplicates. Building it yourself gives you full control over the HTML and makes styling way easier.