Preface
Goal: Bringing responsive pagination, using mobile first.
While writing this CSS code, I can’t claim myself as a developer. Because CSS is not a programming language.
But weird that, responsive design has their own logic. So yeah, I have to code, a little.
Source Code
You can download the source code of this article here.
Extract and run on CLI using $ npm install.
1: Source
I respect copyright. The code below inspired by:
I made a slight modification. But of course the logic remain the same.
Of course, this article is talking about SASS
2: Prepare
This step is required.
Preview: General
This is the complete version.
Configuration
As usual in Hexo - Pagination - Intro.
Layout: EJS Index
Consider use pagination/05-responsive layout, in index.ejs
-
- themes/tutor-05/layout/index.ejs
- gitlab.com/…/layout/index.ejs
SASS: Main
-
- themes/tutor-05/sass/css/main.scss
- gitlab.com/…/sass/main.scss.
// dart-sass --watch -I sass sass/css:source/css/
...
@import "panel"
@import "blog"
@import "list"
@import "pagination"
3: Navigation: HTML Class
The Final Result.
Consider have a look at the image below.
The HTML that we want to achieve is similar as below.
<nav class="pagination is-small is-centered" ...>
<ul class="pagination-list">
<!-- Previous Page. -->
<li class="blog-previous"><a class="pagination-previous" ...>« </a></li>
<!-- First Page. -->
<li class="first"><a class="pagination-link" ...>1</a></li>
<!-- Early (More Pages) Indicator. -->
<li class="pages-indicator first"><span class="pagination-ellipsis">…</span></li>
<li class="pagination--offset-2"><a class="pagination-link" ...>3</a></li>
<li class="pagination--offset-1"><a class="pagination-link" ...>4</a></li>
<li class="pagination--offset-0"><a class="pagination-link is-current" ...>5</a></li>
<li class="pagination--offset-1"><a class="pagination-link" ...>6</a></li>
<li class="pagination--offset-2"><a class="pagination-link" ...>7</a></li>
<!-- Late (More Pages) Indicator. -->
<li class="pages-indicator last"><span class="pagination-ellipsis">…</span></li>
<!-- Last Page. -->
<li class="last"><a class="pagination-link" ...>9</a></li>
<!-- Next Page. -->
<li class="blog-next"><a class="pagination-next" ...> »</a></li>
</ul>
</nav>
Middle Pagination
All you need to care is, only these lines.
<li class="pagination--offset-2">...</li>
<li class="pagination--offset-1">...</li>
<li class="pagination--offset-0">...</li>
<li class="pagination--offset-1">...</li>
<li class="pagination--offset-2">...</li>
Our short term goal is, to put the pagination–offset class.
Layout: Pagination Code Skeleton
As usual, the skeleton, to show the complexity.
-
- themes/tutor-05/layout/pagination/05-responsive.ejs
- gitlab.com/…/layout/pagination/05-responsive.ejs.
// Variable Initialization.
<nav role="navigation" aria-label="pagination">
<% if (page.total > 1) { %>
<ul class="pagination-list">
// Previous Page.
// First Page.
// Early (More Pages) Indicator.
<%
var cursor;
for (cursor = 1; cursor <= page.total; cursor++) {
// Variable Initialization
if (page.total > max_links) {
// Complex page numbers.
// Check between these three:
// * Lower limit pages, or
// * Upper limit pages, or
// * Middle pages.
} else {
// Simple page numbers.
...
}
// Calculate Offset Class.
...
// Show Pager.
...
<% } %>
// Late (More Pages) Indicator.
// Last Page.
// Next Page.
</ul>
<% } %>
</nav>
Calculate Offset Value
Notice this part:
// Calculate Offset Class.
var page_offset_class = 'pagination--offset-'
+ Math.abs(cursor - current);
Notice the new variable called page_offset_class.
Using Offset Class
All we need is just adding the offset class.
<li class="<%= page_offset_class %>">
...
</li>
The real code, is also not very simple.
<li class="<%= page_offset_class %>">
<% if (current != cursor) { %>
<a href="<%= pagination_url(cursor) %>"
class="pagination-link"
aria-label="Goto page <%= cursor %>">
<%= cursor %>
</a>
<% } else { %>
<a class="pagination-link is-current"
aria-label="Page <%= current %>">
<%= current %>
</a>
<% } %>
</li>
Combined Code
if (show_cursor_flag) {
// Calculate Offset Class.
var page_offset_class = 'pagination--offset-'
+ Math.abs(cursor - current);
// Show Pager.
%>
<li class="<%= page_offset_class %>">
<% if (current != cursor) { %>
<a href="<%= pagination_url(cursor) %>"
class="pagination-link"
aria-label="Goto page <%= cursor %>">
<%= cursor %>
</a>
<% } else { %>
<a class="pagination-link is-current"
aria-label="Page <%= current %>">
<%= current %>
</a>
<% } %>
</li>
<% } /* if */ %>
<% } /* for */ %>
That is all. Now that the HTML part is ready, we should go on, by setting up the responsive breakpoints using SCSS.
- .
4: Responsive: Breakpoints
Responsive is easy if you understand the logic.
It is all about breakpoints.
Preview: Each Breakpoint
Consider again, have a look at the animation above, frame by frame. We have at least five breakpoint as six figures below:
SASS: Bulma Custom Breakpoint Variables.
I’m using custom breakpoint, instead of Bulma 7.x breakpoints.
-
- themes/tutor-05/sass/css/_pagination.scss
- gitlab.com/…/sass/_pagination.scss.
// Breakpoint
$xs1: 0
$xs2: 320px
$xs3: 400px
$xs4: 480px
$sm1: 576px
$sm2: 600px
$md: 768px
$lg: 992px
$xl: 1200px
The name inspired by Bootsrap, but it has nothing do with Bootstrap.
SASS: Bulma Breakpoint Skeleton
With breakpoint above, we can setup css skeleton, with empty css rules.
ul.pagination-list
+from($xs1)
+from($xs2)
+from($xs3)
+from($xs4)
+from($sm1)
+from($sm2)
+from($md)
+from($lg)
+from($xl)
SASS: Using Bulma Breakpoint: Simple
We can fill any rules, as below:
+tablet
li.blog-previous a:after
content: " previous"
li.blog-next a:before
content: "next "
SASS: Using Custom Breakpoint: Pagination Offset
We can fill any rules, inside pagination class as below:
// Responsiveness
ul.pagination-list
li.pagination--offset-1,
li.pagination--offset-2,
li.pagination--offset-3,
li.pagination--offset-4,
li.pagination--offset-5,
li.pagination--offset-6,
li.pagination--offset-7
display: none
+from($xs3)
li.pagination--offset-1
display: inline-block
+from($xs4)
li.pagination--offset-2
display: inline-block
+from($sm1)
li.pagination--offset-3
display: inline-block
+from($sm2)
li.pagination--offset-4
display: inline-block
+from($md)
li.pagination--offset-5,
li.pagination--offset-6
display: inline-block
+from($lg)
li.pagination--offset-7
display: inline-block
This setup breakpoint is actually up to you. You may change ti suit whatever you need.
SASS: Responsive Indicator
You can also add CSS rules for indicator.
// Responsiveness
ul.pagination-list
li.first,
li.last,
li.pages-indicator
display: none
+from($xs2)
li.pages-indicator
display: inline-block
+from($sm1)
li.first,
li.last
display: inline-block
Short and simple.
SASS: Hover Effect
If you desire, a slight enhancement without breaking the original looks, hover is a good idea.
// hover color
ul.pagination-list li
a:hover
box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15)
background-color: $yellow
color: #000
a.is-current:hover
background-color: $gray
color: #fff
SASS: Complete Code
Now you can have the complete code as below:
-
- themes/tutor-05/sass/css/_pagination.scss
- gitlab.com/…/sass/_pagination.scss.
+tablet
li.blog-previous a:after
content: " previous"
li.blog-next a:before
content: "next "
// Breakpoint
$xs1: 0
$xs2: 320px
$xs3: 400px
$xs4: 480px
$sm1: 576px
$sm2: 600px
$md: 768px
$lg: 992px
$xl: 1200px
// Responsiveness
ul.pagination-list
li.first,
li.last,
li.pages-indicator
display: none
li.pagination--offset-1,
li.pagination--offset-2,
li.pagination--offset-3,
li.pagination--offset-4,
li.pagination--offset-5,
li.pagination--offset-6,
li.pagination--offset-7
display: none
+from($xs1)
+from($xs2)
li.pages-indicator
display: inline-block
+from($xs3)
li.pagination--offset-1
display: inline-block
+from($xs4)
li.pagination--offset-2
display: inline-block
+from($sm1)
li.first,
li.last,
li.pagination--offset-3
display: inline-block
+from($sm2)
li.pagination--offset-4
display: inline-block
+from($md)
li.pagination--offset-5,
li.pagination--offset-6
display: inline-block
+from($lg)
li.pagination--offset-7
display: inline-block
+from($xl)
// hover color
ul.pagination-list li
a:hover
box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15)
background-color: $yellow
color: #000
a.is-current:hover
background-color: $gray
color: #fff
5: Summary
You can have a look at our complete code here:
-
- themes/tutor-05/layout/pagination/05-responsive.ejs
- gitlab.com/…/layout/pagination/05-responsive.ejs.
<%
/*
* Helper function
*/
function pagination_url(number) {
var path;
// default for index
var path = config.index_generator.path;
// dirty quick fix, avoid double (//)
if (path=='/') { path = '' }
if (is_archive()){
path = '/' + config.archive_dir;
if (is_month()){
// trailing zero
var month = ( page.month < 10 ? '0' + page.month : page.month );
path += '/' + page.year + '/' + month;
} else if (is_year()){
path += '/' + page.year;
}
} else if (is_category()){
path = '/' + config.category_dir + '/' + page.category;
} else if (is_tag()){
path = '/' + config.tag_dir + '/' + page.tag;
}
if (number>1) {
path = path + '/' + config.pagination_dir + '/' + number;
}
return url_for(path);
}
/*
* Pagination links
* https://glennmccomb.com/articles/how-to-build-custom-hugo-pagination/
* Adjacent: Number of links either side of the current page
*/
var current = page.current;
var adjacent_links = 2;
var max_links = (adjacent_links * 2) + 1;
var lower_limit = 1 + adjacent_links;
var upper_limit = page.total - adjacent_links;
%>
<nav class="pagination is-small is-centered"
role="navigation" aria-label="pagination">
<% if (page.total > 1) { %>
<ul class="pagination-list">
<!-- Previous Page. -->
<li class="blog-previous">
<% if (page.prev_link) { %>
<a class="pagination-previous"
href="<%= url_for(page.prev_link) %>"
rel="prev">« </a>
<% } else { %>
<a class="pagination-previous"
title="This is the first page"
disabled>« </a>
<% } %>
</li>
<% if (page.total > max_links) { %>
<% if (current - adjacent_links > 1) { %>
<!-- First Page. -->
<li class="first">
<a href="<%= pagination_url(1) %>"
class="pagination-link"
aria-label="Goto page 1"
>1</a>
</li>
<% } %>
<% if (current - adjacent_links > 2) { %>
<!-- Early (More Pages) Indicator. -->
<li class="pages-indicator first">
<span class="pagination-ellipsis">…</span>
</li>
<% } %>
<% } %>
<%
var cursor;
for (cursor = 1; cursor <= page.total; cursor++) {
var show_cursor_flag = false;
if (page.total > max_links) {
// Complex page numbers.
if (current <= lower_limit) {
// Lower limit pages.
// If the user is on a page which is in the lower limit.
if (cursor <= max_links) {
// If the current loop page is less than max_links.
show_cursor_flag = true;
}
} else if (current >= upper_limit) {
// Upper limit pages.
// If the user is on a page which is in the upper limit.
if (cursor > (page.total - max_links)) {
// If the current loop page is less than max_links.
show_cursor_flag = true;
}
} else {
// Middle pages.
if ( (cursor >= current - adjacent_links)
&& (cursor <= current + adjacent_links) ) {
show_cursor_flag = true;
}
}
} else {
// Simple page numbers.
show_cursor_flag = true;
}
if (show_cursor_flag) {
// Calculate Offset Class.
var page_offset_class = 'pagination--offset-'
+ Math.abs(cursor - current);
// Show Pager.
%>
<li class="<%= page_offset_class %>">
<% if (current != cursor) { %>
<a href="<%= pagination_url(cursor) %>"
class="pagination-link"
aria-label="Goto page <%= cursor %>">
<%= cursor %>
</a>
<% } else { %>
<a class="pagination-link is-current"
aria-label="Page <%= current %>">
<%= current %>
</a>
<% } %>
</li>
<% } /* if */ %>
<% } /* for */ %>
<% if (page.total > max_links) { %>
<% if (current + adjacent_links < page.total - 1) { %>
<!-- Late (More Pages) Indicator. -->
<li class="pages-indicator last">
<span class="pagination-ellipsis">…</span>
</li>
<% } %>
<% if (current + adjacent_links < page.total) { %>
<!-- Last Page. -->
<li class="last">
<a href="<%= pagination_url(page.total) %>"
class="pagination-link"
aria-label="Goto page <%= page.total %>"
><%= page.total %></a>
</li>
<% } %>
<% } %>
<!-- Next Page. -->
<li class="blog-next">
<% if (page.next_link) { %>
<a class="pagination-next"
href="<%= url_for(page.next_link) %>"
rel="next"> »</a>
<% } else { %>
<a class="pagination-next"
title="This is the last page"
disabled> »</a>
<% } %>
</li>
</ul>
<% } %>
</nav>
We will have to complete the code later, in the next article. This has been a long article. We still need a few changes, for screen reader.
- .
Browser: Pagination Preview
Finally the animated version.
What is Next ?
Looks good right? This kitten, is still with me. Just like the kitten, do not get rest yet! Our pagination tutorial still have some materials to go.
Consider continue reading [ Hexo - Pagination - Screen Reader ]. There are, some interesting topic about Pagination in Hexo.
Thank you for reading.