Preface
Goal: Bringing responsive pagination, using mobile first.
Source Code
This article use tutor-07 theme. We will create it step by step.
1: Source
Original 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
Altered Source
Coder will feel like home
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.
2: Prepare
This step is required.
Preview: General
This is what we want to achieve in this tutorial.
Layout: Nunjucks Blog
Consider use pagination/05-responsive
partial, in blog.njk
.
{% include "pagination/05-responsive.njk" %}
SASS: Main
...
// Tailor Made
@import "main/layout-page"
@import "main/layout-content"
@import "main/decoration"
@import "main/pagination"
@import "main/list"
@import "post/content"
@import "post/navigation"
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" ...
><span class="fas fa-step-backward"></span> </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>
<!-- Page numbers. -->
<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" ...
> <span class="fas fa-step-forward"></span></a></li>
</ul>
</nav>
Middle Pagination
All you need to care is, only these lines.
<!-- Page numbers. -->
<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.
Partial: Responsive Skeleton
As usual, the skeleton, to show the complexity.
{% if totalPages > 1 %}
<nav class="pagination is-small is-centered" ...>
<ul class="pagination-list">
<!-- First Page (arrow). -->
<!-- Previous Page (arrow). -->
{% if (totalPages > maxLinks) %}
<!-- First Page (number = 1). -->
<!-- Early (More Pages) Indicator. -->
{% endif %}
<!-- Page numbers. -->
{% for cursor, link in pagination.links | hashIt %}
...
{% endfor %}
{% if (totalPages > maxLinks) %}
<!-- Late (More Pages) Indicator. -->
<!-- Last Page (number = total page). -->
{% endif %}
<!-- Next Page (arrow). -->
<!-- Last Page (arrow). -->
</ul>
</nav>
{% endif %}
Calculate Offset Value
Notice this part:
<!-- Calculate Offset Class. -->
{% set offset = (cursor - current) | abs %}
{% set pageOffsetClass = 'pagination--offset-' + offset %}
Notice the new variable called pageOffsetClass
.
Using Offset Class
All we need is just adding the offset class.
<li class="{{ pageOffsetClass }}">
...
</li>
Combined Code
<!-- Show Pager. -->
{% if showCursorFlag %}
<!-- Calculate Offset Class. -->
{% set offset = (cursor - current) | abs %}
{% set pageOffsetClass = 'pagination--offset-' + offset %}
<li class="{{ pageOffsetClass }}">
{% if cursor == current %}
<a class="pagination-link is-current {{ color }}"
aria-label="Page {{ cursor }}">
{{ cursor }}
</a>
{% else %}
<a class="pagination-link hoverable"
href="{{ link }}"
aria-label="Goto page {{ cursor }}">
{{ cursor }}
</a>
{% endif %}
</li>
{% endif %}
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.
// Breakpoint
$xs1: 0
$xs2: 320px
$xs3: 380px
$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.icon-previous a:after
content: " Previous"
li.icon-next a:before
content: "Next "
li.icon-first a:after
content: " First"
li.icon-last a:before
content: "Last "
li.icon-previous a span.fas,
li.icon-next a span.fas,
li.icon-first a span.fas,
li.icon-last a span.fas
display: none
SASS: Using Custom Breakpoint: Pagination Offset
We can fill any rules, inside pagination-list
class as below:
Such as pagination--offset
setting,
for each custom breakpoints.
// 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($xs1)
+from($xs2)
+from($xs3)
li.pagination--offset-1
display: inline-block
+from($xs4)
li.pagination--offset-2
display: inline-block
+from($sm1)
li.icon-first,
li.icon-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)
This setup breakpoint is actually up to you. You may change to suit whatever you need.
SASS: Responsive Indicator
You can also add CSS rules for indicator, and stuff.
// Responsiveness
ul.pagination-list
li.icon-first,
li.icon-last,
li.pages-indicator
display: none
+from($xs1)
+from($xs2)
li.pages-indicator
display: inline-block
+from($sm1)
li.icon-first,
li.icon-last,
Short and simple.
SASS: Decoration
If you desire, a slight enhancement without breaking the original looks.
Hover is a good idea.
// hover color
ul.pagination-list li
a:hover
background-color: map-get($yellow, 'lighten-2')
color: #000
a.is-current:hover
background-color: map-get($grey, 'base') !important
color: #fff
And so is gap margin.
// layout
nav.pagination
margin-top: 10px
margin-bottom: 10px
SASS: Complete Code
Now you can have the complete code as below:
+tablet
li.icon-previous a:after
content: " Previous"
li.icon-next a:before
content: "Next "
li.icon-first a:after
content: " First"
li.icon-last a:before
content: "Last "
li.icon-previous a span.fas,
li.icon-next a span.fas,
li.icon-first a span.fas,
li.icon-last a span.fas
display: none
// Breakpoint
$xs1: 0
$xs2: 320px
$xs3: 380px
$xs4: 480px
$sm1: 576px
$sm2: 600px
$md: 768px
$lg: 992px
$xl: 1200px
// Responsiveness
ul.pagination-list
li.icon-first,
li.icon-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.icon-first,
li.icon-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
background-color: map-get($yellow, 'lighten-2')
color: #000
a.is-current:hover
background-color: map-get($grey, 'base') !important
color: #fff
// layout
nav.pagination
margin-top: 10px
margin-bottom: 10px
5: Summary
You can have a look at our complete code here:
{% set totalPages = pagination.links.length %}
{% set current = pagination.pageNumber + 1 %}
{#
* Pagination links
* https://glennmccomb.com/articles/how-to-build-custom-hugo-pagination/
* Adjacent: Number of links either side of the current page
#}
{% if totalPages > 1 %}
<nav class="pagination is-small is-centered"
role="navigation" aria-label="pagination">
{% set adjacentLinks = 2 %}
{% set maxLinks = (adjacentLinks * 2) + 1 %}
<ul class="pagination-list">
<!-- First Page. -->
<li class="icon-first">
{% if current > 1 %}
<a class="pagination-previous hoverable"
href="{{ pagination.firstPageLink }}"
rel="first">
<span class="fas fa-step-backward"></span> </a>
{% else %}
<a class="pagination-previous"
title="This is the first page"
disabled>
<span class="fas fa-step-backward"></span> </a>
{% endif %}
</li>
<!-- Previous Page. -->
<li class="icon-previous">
{% if pagination.previousPageLink %}
<a class="pagination-previous hoverable"
href="{{ pagination.previousPageLink }}"
rel="prev">
<span class="fas fa-backward"></span> </a>
{% else %}
<a class="pagination-previous"
title="This is the first page"
disabled>
<span class="fas fa-backward"></span> </a>
{% endif %}
</li>
{% if (totalPages > maxLinks) %}
<!-- First Page. -->
{% if (current - adjacentLinks > 1) %}
<li>
<a class="pagination-link hoverable"
href="{{ pagination.firstPageLink }}"
aria-label="Goto page 1">1</a>
</li>
{% endif %}
<!-- Early (More Pages) Indicator. -->
{% if (current - adjacentLinks > 2) %}
<li class="pages-indicator">
<span class="pagination-ellipsis">…</span>
</li>
{% endif %}
{% endif %}
<!-- Page numbers. -->
{% for cursor, link in pagination.links | hashIt %}
<!-- Adjacent script based on Glenn Mc Comb. -->
{% set showCursorFlag = cursor |
isShowAdjacent(current, totalPages, adjacentLinks) %}
<!-- Show Pager. -->
{% if showCursorFlag %}
<!-- Calculate Offset Class. -->
{% set offset = (cursor - current) | abs %}
{% set pageOffsetClass = 'pagination--offset-' + offset %}
<li class="{{ pageOffsetClass }}">
{% if cursor == current %}
<a class="pagination-link is-current {{ color }}"
aria-label="Page {{ cursor }}">
{{ cursor }}
</a>
{% else %}
<a class="pagination-link hoverable"
href="{{ link }}"
aria-label="Goto page {{ cursor }}">
{{ cursor }}
</a>
{% endif %}
</li>
{% endif %}
{% endfor %}
{% if (totalPages > maxLinks) %}
<!-- Late (More Pages) Indicator. -->
{% if (current + adjacentLinks < totalPages - 1) %}
<li class="pages-indicator">
<span class="pagination-ellipsis">…</span>
</li>
{% endif %}
<!-- Last Page. -->
{% if (current + adjacentLinks < totalPages) %}
<li>
<a class="pagination-link hoverable"
href="{{ pagination.lastPageLink }}"
aria-label="Goto page {{ totalPages }}">
{{ totalPages }}</a>
</li>
{% endif %}
{% endif %}
<!-- Next Page. -->
<li class="icon-next">
{% if pagination.nextPageLink %}
<a class="pagination-next hoverable"
href="{{ pagination.nextPageLink }}"
rel="next">
<span class="fas fa-forward"></span></a>
{% else %}
<a class="pagination-next"
title="This is the last page"
disabled>
<span class="fas fa-forward"></span></a>
{% endif %}
</li>
<!-- Last Page. -->
<li class="icon-last">
{% if current != totalPages %}
<a class="pagination-next hoverable"
href="{{ pagination.lastPageLink }}"
rel="last">
<span class="fas fa-step-forward"></span></a>
{% else %}
<a class="pagination-next"
title="This is the last page"
disabled>
<span class="fas fa-step-forward"></span></a>
{% endif %}
</li>
</ul>
</nav>
{% endif %}
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 ?
Consider continue reading [ Eleventy - Pagination - Screenreader ]. We are going to conclude pagination with screenreader.
Thank you for reading.