How To Add Custom WordPress Pagination Without a Plugin
For a WordPress blog, pagination is used to display a limited number of posts per page. Compared to the default WordPress page navigation, numbered pagination allows users the ability to navigate much easier and deeper into the archives, like numbered pages of a book. Pagination is used in almost every Web application to display returned data on multiple pages. More…
A custom numbered pagination will enhance the SEO value of your blog. It enhances users´ experience by allowing them to easily access pages in your archives. It also makes the job easier for search engine robots to crawl your posts especially for complex blogs.
Default WordPress Page Navigation
If you have plenty of posts in your WordPress blog, and depending on your settings, you probably have at the bottom of your home page a « Previous and/or Next » links. These 2 links connects neighboring content and enable users to navigate through other posts.
The following picture shows the default WordPress page navigation:
The following picture shows the modified default page navigation that I had in this blog prior to adding the custom numbered pagination code:
Many people, including myself, are not happy with just using the default WordPress page navigation. It looks ugly, dull and most importantly is not SEO and user friendly. We want a nicer and more appealing custom numbered pagination. This is where this tutorial helps.
Custom WordPress Pagination
The picture below shows the custom numbered pagination generated for this blog.
If you are wondering how I created 16 pages but I currently have 4, the answer is simple, reduce the number of posts displayed per page in your WordPress dashboard (Settings -> Reading).
Yes, there are plugins for WordPress pagination, such as WP-PageNavi being the most popular and several others. But haven´t you read my previous post about the disadvantages of going crazy adding plugins to your theme? Also what would you do if you want to develop a premium theme with a built-in custom numbered pagination.
WordPress Numbered Pagination Code
This is my version of the numbered pagination code. Open the functions.php file located in your theme´s folder and add (copy and paste) the following two functions. This code is tested to work for the current WordPress version.
CODE-X :: Pagination (Numbered Page Navigation) Code
Note: To scroll within the code: You can also click on the code window and use your keyboard´s arrow keys.
<?php /******************************************************************* * @Author: Boutros AbiChedid * @Date: March 20, 2011 * @Websites: http://bacsoftwareconsulting.com/ * http://blueoliveonline.com/ * @Description: Numbered Page Navigation (Pagination) Code. * @Tested: Up to WordPress version 3.1.2 (also works on WP 3.3.1) ********************************************************************/ /* Function that Rounds To The Nearest Value. Needed for the pagenavi() function */ function round_num($num, $to_nearest) { /*Round fractions down (http://php.net/manual/en/function.floor.php)*/ return floor($num/$to_nearest)*$to_nearest; } /* Function that performs a Boxed Style Numbered Pagination (also called Page Navigation). Function is largely based on Version 2.4 of the WP-PageNavi plugin */ function pagenavi($before = '', $after = '') { global $wpdb, $wp_query; $pagenavi_options = array(); $pagenavi_options['pages_text'] = ('Page %CURRENT_PAGE% of %TOTAL_PAGES%:'); $pagenavi_options['current_text'] = '%PAGE_NUMBER%'; $pagenavi_options['page_text'] = '%PAGE_NUMBER%'; $pagenavi_options['first_text'] = ('First Page'); $pagenavi_options['last_text'] = ('Last Page'); $pagenavi_options['next_text'] = 'Next »'; $pagenavi_options['prev_text'] = '« Previous'; $pagenavi_options['dotright_text'] = '...'; $pagenavi_options['dotleft_text'] = '...'; $pagenavi_options['num_pages'] = 5; //continuous block of page numbers $pagenavi_options['always_show'] = 0; $pagenavi_options['num_larger_page_numbers'] = 0; $pagenavi_options['larger_page_numbers_multiple'] = 5; //If NOT a single Post is being displayed /*http://codex.wordpress.org/Function_Reference/is_single)*/ if (!is_single()) { $request = $wp_query->request; //intval — Get the integer value of a variable /*http://php.net/manual/en/function.intval.php*/ $posts_per_page = intval(get_query_var('posts_per_page')); //Retrieve variable in the WP_Query class. /*http://codex.wordpress.org/Function_Reference/get_query_var*/ $paged = intval(get_query_var('paged')); $numposts = $wp_query->found_posts; $max_page = $wp_query->max_num_pages; //empty — Determine whether a variable is empty /*http://php.net/manual/en/function.empty.php*/ if(empty($paged) || $paged == 0) { $paged = 1; } $pages_to_show = intval($pagenavi_options['num_pages']); $larger_page_to_show = intval($pagenavi_options['num_larger_page_numbers']); $larger_page_multiple = intval($pagenavi_options['larger_page_numbers_multiple']); $pages_to_show_minus_1 = $pages_to_show - 1; $half_page_start = floor($pages_to_show_minus_1/2); //ceil — Round fractions up (http://us2.php.net/manual/en/function.ceil.php) $half_page_end = ceil($pages_to_show_minus_1/2); $start_page = $paged - $half_page_start; if($start_page <= 0) { $start_page = 1; } $end_page = $paged + $half_page_end; if(($end_page - $start_page) != $pages_to_show_minus_1) { $end_page = $start_page + $pages_to_show_minus_1; } if($end_page > $max_page) { $start_page = $max_page - $pages_to_show_minus_1; $end_page = $max_page; } if($start_page <= 0) { $start_page = 1; } $larger_per_page = $larger_page_to_show*$larger_page_multiple; //round_num() custom function - Rounds To The Nearest Value. $larger_start_page_start = (round_num($start_page, 10) + $larger_page_multiple) - $larger_per_page; $larger_start_page_end = round_num($start_page, 10) + $larger_page_multiple; $larger_end_page_start = round_num($end_page, 10) + $larger_page_multiple; $larger_end_page_end = round_num($end_page, 10) + ($larger_per_page); if($larger_start_page_end - $larger_page_multiple == $start_page) { $larger_start_page_start = $larger_start_page_start - $larger_page_multiple; $larger_start_page_end = $larger_start_page_end - $larger_page_multiple; } if($larger_start_page_start <= 0) { $larger_start_page_start = $larger_page_multiple; } if($larger_start_page_end > $max_page) { $larger_start_page_end = $max_page; } if($larger_end_page_end > $max_page) { $larger_end_page_end = $max_page; } if($max_page > 1 || intval($pagenavi_options['always_show']) == 1) { /*http://php.net/manual/en/function.str-replace.php */ /*number_format_i18n(): Converts integer number to format based on locale (wp-includes/functions.php*/ $pages_text = str_replace("%CURRENT_PAGE%", number_format_i18n($paged), $pagenavi_options['pages_text']); $pages_text = str_replace("%TOTAL_PAGES%", number_format_i18n($max_page), $pages_text); echo $before.'<div class="pagenavi">'."\n"; if(!empty($pages_text)) { echo '<span class="pages">'.$pages_text.'</span>'; } //Displays a link to the previous post which exists in chronological order from the current post. /*http://codex.wordpress.org/Function_Reference/previous_post_link*/ previous_posts_link($pagenavi_options['prev_text']); if ($start_page >= 2 && $pages_to_show < $max_page) { $first_page_text = str_replace("%TOTAL_PAGES%", number_format_i18n($max_page), $pagenavi_options['first_text']); //esc_url(): Encodes < > & " ' (less than, greater than, ampersand, double quote, single quote). /*http://codex.wordpress.org/Data_Validation*/ //get_pagenum_link():(wp-includes/link-template.php)-Retrieve get links for page numbers. echo '<a href="'.esc_url(get_pagenum_link()).'" class="first" title="'.$first_page_text.'">1</a>'; if(!empty($pagenavi_options['dotleft_text'])) { echo '<span class="expand">'.$pagenavi_options['dotleft_text'].'</span>'; } } if($larger_page_to_show > 0 && $larger_start_page_start > 0 && $larger_start_page_end <= $max_page) { for($i = $larger_start_page_start; $i < $larger_start_page_end; $i+=$larger_page_multiple) { $page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $pagenavi_options['page_text']); echo '<a href="'.esc_url(get_pagenum_link($i)).'" class="single_page" title="'.$page_text.'">'.$page_text.'</a>'; } } for($i = $start_page; $i <= $end_page; $i++) { if($i == $paged) { $current_page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $pagenavi_options['current_text']); echo '<span class="current">'.$current_page_text.'</span>'; } else { $page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $pagenavi_options['page_text']); echo '<a href="'.esc_url(get_pagenum_link($i)).'" class="single_page" title="'.$page_text.'">'.$page_text.'</a>'; } } if ($end_page < $max_page) { if(!empty($pagenavi_options['dotright_text'])) { echo '<span class="expand">'.$pagenavi_options['dotright_text'].'</span>'; } $last_page_text = str_replace("%TOTAL_PAGES%", number_format_i18n($max_page), $pagenavi_options['last_text']); echo '<a href="'.esc_url(get_pagenum_link($max_page)).'" class="last" title="'.$last_page_text.'">'.$max_page.'</a>'; } next_posts_link($pagenavi_options['next_text'], $max_page); if($larger_page_to_show > 0 && $larger_end_page_start < $max_page) { for($i = $larger_end_page_start; $i <= $larger_end_page_end; $i+=$larger_page_multiple) { $page_text = str_replace("%PAGE_NUMBER%", number_format_i18n($i), $pagenavi_options['page_text']); echo '<a href="'.esc_url(get_pagenum_link($i)).'" class="single_page" title="'.$page_text.'">'.$page_text.'</a>'; } } echo '</div>'.$after."\n"; } } } ?>
After adding the above 2 functions (CODE-X) to your functions.php file and uploaded it to your server, copy and paste the code below in multiple files: index.php, archive.php, search.php, and probably other files located in your theme´s folder. Place the code where you want the page navigation to appear. Make sure to delete the default page navigation code.
CODE-Y :: Adding pagenavi Function
<div class="navigation"> <!-- REMOVE default page navigation once your custom pagination is working. --> <?php //REMOVE DEFAULT: next_posts_link('«« Older Posts') //REMOVE DEFAULT: previous_posts_link('Newer Posts »»') ?> <!-- ADD Custom Numbered Pagination code. --> <?php if(function_exists('pagenavi')) { pagenavi(); } ?> </div>
Depending on your theme, the code above could be placed in your footer.php file. Frankly, this would be the ideal place, since you will need to add it once.
The Conditional check is to make sure that “pagenavi” function exists, to prevent any erros in case you forgot to add CODE-X first.
Styling the Custom Pagination
Finally we need to style the numbered pagination code with CSS. The following CSS code is what I used to style the pagination for this blog. The code should be added to your theme´s CSS file (usually called style.css). Of course go ahead and change it to fit your design.
CODE-Z :: Styling The Pagination Code
Note: To scroll within the code: You can also click on the code window and use your keyboard´s arrow keys.
/******************************************************************* * @Author: Boutros AbiChedid * @Date: March 20, 2011 * @Websites: http://bacsoftwareconsulting.com/ * http://blueoliveonline.com/ * @Description: Styling Custom Numbered Page Navigation (Pagination) ********************************************************************/ .pagenavi { margin: 0 0 20px 30px; padding: 5px 1px 5px; float:left; width: 98%; background:url(images/pagination_bg.gif) no-repeat center; } .pagenavi a { padding: 5px 6px 4px 6px; margin: 3px; text-decoration: none; border: 1px solid #ccc; color: #666; background-color: inherit; } .pagenavi a:hover { border: 1px solid #444; color: #444; background-color: #eee; } .pagenavi span.pages { padding: 5px 6px 4px 6px; margin: 3px; color: #825a2d; font-weight:bold; border: 1px solid #999; background-color: inherit; } .pagenavi span.current { padding: 5px 6px 4px 6px; margin: 3px; font-weight:bold; border: 1px solid #666; color: #444; background-color: #eee; } .pagenavi span.expand { padding: 5px 6px 4px 6px; margin: 3px; border: 1px solid #ccc; color: #444; background-color: inherit; } .pagenavi .first, .pagenavi .last { border: 1px solid #aaa; } .pagenavi .single_page { border: 1px dashed #ccc; }
Conclusion
You now have a custom numbered pagination that can be used on your WordPress Website, which is nicer, user friendlier, and has better SEO advantage than the default. If you have any questions or anything else to say, make sure to leave a comment!
category is repeating in pagination
I am using this code to break category in pagination and showing 5-5 chunks in pagination. I have 50 categories in a WordPress site. I wants to show each five categories on one page and next 5 on next page and next 5 on next page and so on with pagination.
Why this code is repeating category in pagination.
Nice information, thanks man, i am looking for this.
Hi !
I Developed the custom post type wp plugin but I can’t add pagination. How to add the pagination? here ismy script. Please let me know how to solve this.
Portfolio
‘Portfolio’,'posts_per_page’ => 4)); ?>
‘Portfolio’, ‘posts_per_page’ => 4 ); $loop = new WP_Query( $mypost ); ?>
have_posts() ) : $loop->the_post(); {?>
Is there a way to put a style class for the Previous and next class?
Yes.
On lines 28 and 29 of the code you replace them with the following:
Notice that I wrapped them with ‘next’ and ‘previous’ classes that you can define in your theme’s ‘style.css’ file.
Hope this helps.
Boutros.
AWESOME!!! This really helped me out!! I know the wp-pagenavi plugin uses the same functionality but that doesn’t work with custom SQL queries.
This does, just had to manually fill in some variables and it works great!
That’s great Erik.
Thank you for this, it works perfectly. However, When there’s not enough posts to spread through out 5 pages (say there’s only 2 posts and they will fit in one page), pagination will still show 1 – 5 pages. Any idea why this is happening.
Thanks again.
It shouldn’t do that. I think that have to do with your theme. There a plugin conflict, somewhere? or some built in code in your theme?
I suggest that you temporarily switch to a different theme and try my pagination code and see if you still get the same behavior.
Thanks.
Boutros.
Hi. Thanks for this. At first I was having trouble until I really looked at your function. The global declaration of $wp_query wasn’t relevant to how I structured by custom post loops. So, I just passed my query variable to your function and it worked like a charm!!!
Thank you for this great pagination, I use it on my new blog!
Hi,love this solution for pagnitation,however,i used this code:
Posted by Furqan on: April 11, 2012 at 12:08 PM http://pastie.org/4288302
and this is my page code:http://pastie.org/4288312
everything shows up ok,but when i click on 2,3,or 4 it redirects me to my first page instead of next post page.I have costum template and i use /%postname%/ as permalink, i know there is something wrong with my query_posts,but i dont have any idea how to fix it . Any ideas whats wrong with my code?
thnx.
Hi,
If you want me to hep you for your specific needs, then please donate first to this blog.
Let me know. Thanks.
Boutros.
Hi,
Does this code work on the adventure-journal 1.0 theme?
I have added your code to a different theme with no problem, but when I add it to this theme it doesn’t work.
Thank you.
Hi Adriana,
I don’t know if the code works or not for that specific theme. You have to try it out.
On some themes like ‘magazeen’ theme, the code won’t work where there are more than one loop in “index.php”. Check the index.php file for that theme and see if there are more than one loop.
See comment: http://bacsoftwareconsulting.com/blog/index.php/web-programming/add-custom-wordpress-pagination-without-plugin/comment-page-1/#comment-2248
If you want me to help you further, then a donation is required first.
Thanks.
Boutros.
I got it to work. thank you!!! Great script :)
Hi, I tried this code and I can see it on my page, but when I click on the second or third page, for example, it doesn’t work. How can I resolve that? Sorry for my bad english :)
Hi Lisa,
what WordPress theme are you using (link for the theme?) And show me an example (another link).
I can’t tell from your generic problem.
Thanks
Hi, thanks a lot for your help. I am creating a custom theme, but I have a problem with wordpress too, when I create a news page and I pubblish it, the page in front end is pubblished, but in back end I see a white page, maybe it’s a error of wordpress instalaltion. I have already wp installed and i created a new folder inside (my site is lisadamus.it and i created a forder called lisa and a new installation of wp inside, maybe this is a problem), however…..I installed wordpress_it_IT_3_3_2 into lisa folder and you can see there the problem with the page navigation. I haven’t installed plugin in lisa yet, so i cannot have conflict.
Look here
http://www.lisadamus.it/lisa/?page_id=2
Thanks a lot for your help
Hi Lisa,
I am not really sure what’s going on with your theme.
But first I would start with your WordPress installation. If you suspect that you have something weird going on, you probably should re-install WordPress.
From the page link that you gave me, It seems to me that you are using custom post types and not just normal posts. The pagination code should still work for custom post types though.
The pagination code have been used dozens of times with no problems. Only one case I heard of a problem similar to yours:
Check the comment (http://bacsoftwareconsulting.com/blog/index.php/web-programming/add-custom-wordpress-pagination-without-plugin/comment-page-2/#comment-4053)
Also I have a separate tutorial for custom post types: http://bacsoftwareconsulting.com/blog/index.php/wordpress-cat/pagination-for-custom-post-types-in-wordpress-without-a-plugin/
I am not sure what WP version you are using (I hope the latest). I am on a restricted computer where I can’t access the source code.
If you want me to debug your problem and get the code to work on your theme, then it will cost you and it won’t be free.
Let me know if you find the problem.
Boutros.
Thanks, I understood that the problem is into functions.php file, i will try to resolve it.
Thansk a lot for your help, you are great.