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.
1: Source
I respect copyright. The code below inspired by:
I made a slight modification. But of course the logic remain the same.
2: Prepare
Preview: General
This is the complete version.
Layout: List
As usual, change the script to use responsive partial.
{{ $paginator := .Paginate (where .Site.Pages "Type" "post") }}
{{ partial "pagination-responsive.html" (dict "p" $paginator "s" .Scratch) }}
Partial: Minimal Pagination Code
You should have this artefact, before you begin.
- themes/tutor-05/layouts/partials/pagination-responsive.html : gitlab.com/…/partials/pagination-responsive.html.
<nav aria-label="Page navigation">
{{ $s := .s }}
{{ $p := .p }}
{{ if gt $p.TotalPages 1 }}
<ul class="pagination justify-content-center">
...
</ul>
{{ end }}
</nav>
SASS: Main
-
- themes/tutor-05/sass/css/main.scss
- gitlab.com/…/sass/main.scss.
@import
// taken from bootstrap
// ...
// variables
"bootstrap/functions",
"variables",
"bootstrap/variables",
"bootstrap/mixins/breakpoints",
// custom
// ...
"pagination"
;
SASS: Custom Pagination
I’m using Bootstrap 4 grid breakpoints.
-
- themes/tutor-05/sass/css/_pagination.scss
- gitlab.com/…/sass/_pagination.scss.
@include media-breakpoint-up(md) {
...
}
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.
<ul class="pagination justify-content-center">
<li class="page-item blog_previous">...</li>
<li class="page-item first">...</li>
<li class="pages-indicator first disabled">...</li>
<li class="page-item pagination--offset-2">...</li>
<li class="page-item pagination--offset-1">...</li>
<li class="page-item pagination--offset-0 active ">...</li>
<li class="page-item pagination--offset-1">...</li>
<li class="page-item pagination--offset-2">...</li>
<li class="pages-indicator last disabled">...</li>
<li class="page-item last">...</li>
<li class="page-item blog_next">...</li>
</ul>
Middle Pagination
All you need to care is, only these lines.
<li class="page-item pagination--offset-2">...</li>
<li class="page-item pagination--offset-1">...</li>
<li class="page-item pagination--offset-0 active ">...</li>
<li class="page-item pagination--offset-1">...</li>
<li class="page-item pagination--offset-2">...</li>
Our short term goal is, to put the pagination–offset class.
Partial: Pagination Code Skeleton
As usual, the skeleton, to show the complexity.
- themes/tutor-05/layouts/partials/pagination-responsive.html : gitlab.com/…/partials/pagination-responsive.html.
<nav aria-label="Page navigation">
{{ $s := .s }}
{{ $p := .p }}
{{ if gt $p.TotalPages 1 }}
<ul class="pagination justify-content-center">
<!-- Variable Initialization. -->
<!-- Previous Page. -->
<!-- First Page. -->
<!-- Early (More Pages) Indicator. -->
{{- range $p.Pagers -}}
{{ $s.Set "page_number_flag" false }}
{{ $s.Set "page_offset" false }}
<!-- Complex page numbers. -->
{{ if gt $p.TotalPages $max_links }}
<!-- Lower limit pages. -->
<!-- Upper limit pages. -->
<!-- Middle pages. -->
<!-- Simple page numbers. -->
{{ else }}.
...
{{ end }}
<!-- Calculate Offset Class. -->
<!-- Show Pager. -->
{{- if eq ($s.Get "page_number_flag") true -}}
...
{{- end -}}
{{ end }}
<!-- Late (More Pages) Indicator. -->
<!-- Last Page. -->
<!-- Next Page. -->
</ul>
{{ end }}
</nav>
Notice the new variable called page_offset.
Partial: Pagination Code: Long Version
Before you begin, consider copy-and-paste from our last tutorial.
- themes/tutor-05/layouts/partials/pagination-indicator.html : gitlab.com/…/partials/pagination-indicator.html.
Calculate Offset Value
It is just a matter of difference, between current page and pager.
<!-- Calculate Offset Class. -->
{{- if eq ($s.Get "page_number_flag") true -}}
{{ $s.Set "page_offset" (sub .PageNumber $p.PageNumber) }}
{{- end -}}
Calculate Offset Class
We require to calculate absolute value, turn the negative value to positive. The issue is that Hugo does not come with abs() function, so the next part is a little bit cryptic.
<!-- Calculate Offset Class. -->
{{- if eq ($s.Get "page_number_flag") true -}}
{{ $s.Set "page_offset" (sub .PageNumber $p.PageNumber) }}
{{ $s.Set "page_offset_class" "" }}
{{- if ge ($s.Get "page_offset") 0 -}}
{{ $s.Set "page_offset_class" (print "pagination--offset-" ($s.Get "page_offset") ) }}
{{- else -}}
{{ $s.Set "page_offset_class" (print "pagination--offset" ($s.Get "page_offset") ) }}
{{- end -}}
{{- end -}}
Using Offset Class
All we need is just adding the offset class.
<li class="page-item {{ $s.Get "page_offset_class" }}">
...
</li>
The real code, is also not very simple.
<!-- Show Pager. -->
{{- if eq ($s.Get "page_number_flag") true -}}
<li class="page-item{{ if eq $pagenumber .PageNumber }} active{{ end }} {{ $s.Get "page_offset_class" }}">
{{ if not (eq $pagenumber .PageNumber) }}
<a href="{{ .URL }}" class="page-link">{{ .PageNumber }}</a>
{{ else }}
<span class="page-link page-item">{{ .PageNumber }}</span>
{{ end }}
</li>
{{- end -}}
Combined Code
{{- if eq ($s.Get "page_number_flag") true -}}
<!-- Calculate Offset Class. -->
{{ $s.Set "page_offset" (sub .PageNumber $p.PageNumber) }}
{{ $s.Set "page_offset_class" "" }}
{{- if ge ($s.Get "page_offset") 0 -}}
{{ $s.Set "page_offset_class" (print "pagination--offset-" ($s.Get "page_offset") ) }}
{{- else -}}
{{ $s.Set "page_offset_class" (print "pagination--offset" ($s.Get "page_offset") ) }}
{{- end -}}
<!-- Show Pager. -->
<li class="page-item{{ if eq $pagenumber .PageNumber }} active{{ end }} {{ $s.Get "page_offset_class" }}">
{{ if not (eq $pagenumber .PageNumber) }}
<a href="{{ .URL }}" class="page-link">{{ .PageNumber }}</a>
{{ else }}
<span class="page-link page-item">{{ .PageNumber }}</span>
{{ end }}
</li>
{{- end -}}
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: Bootstrap Grid Breakpoint Variables.
Bootstrap 4 grid breakpoints are defined as below.
- themes/tutor-05/sass/bootstrap/_variables.scss
// Grid breakpoints
//
// Define the minimum dimensions at which your layout will change,
// adapting to different screen sizes, for use in media queries.
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
SASS: Bootstrap Breakpoint Skeleton
With breakpoint above, we can setup css skeleton, with empty css rules.
ul.pagination {
@include media-breakpoint-up(xs) {}
@include media-breakpoint-up(sm) {}
@include media-breakpoint-up(md) {}
@include media-breakpoint-up(lg) {}
@include media-breakpoint-up(xl) {}
}
SASS: Using Bootstrap Breakpoint: Simple
We can fill any rules, as below:
@include media-breakpoint-up(md) {
.blog_previous {
span.page-link:after,
a.page-link:after {
content: " previous"
}
}
.blog_next {
span.page-link:before,
a.page-link:before {
content: "next "
}
}
}
SASS: Using Bootstrap Breakpoint: Pagination Offset
We can fill any rules, inside pagination class as below:
ul.pagination {
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;
}
@include media-breakpoint-up(xs) {
}
@include media-breakpoint-up(sm) {
li.pagination--offset-1,
li.pagination--offset-2 {
display: inline-block;
}
}
@include media-breakpoint-up(md) {
li.pagination--offset-3,
li.pagination--offset-4 {
display: inline-block;
}
}
@include media-breakpoint-up(lg) {
li.pagination--offset-5,
li.pagination--offset-6,
li.pagination--offset-7 {
display: inline-block;
}
}
@include media-breakpoint-up(xl) {
}
}
SASS: Responsive Indicator
You can also add CSS rules for indicator.
ul.pagination {
li.first,
li.last,
li.pages-indicator {
display: none;
}
@include media-breakpoint-up(xs) {
}
@include media-breakpoint-up(sm) {
li.pages-indicator {
display: inline-block;
}
}
@include media-breakpoint-up(md) {
li.first,
li.last {
display: inline-block;
}
}
@include media-breakpoint-up(lg) {
}
@include media-breakpoint-up(xl) {
}
}
SASS: Enhanced Bootstrap Breakpoint
If you desire smoother transition effect, you can create your own breakpoint, beyond bootstrap.
$grid-breakpoints-custom: (
xs: 0,
xs2: 320px,
xs3: 400px,
xs4: 480px,
sm: 576px,
sm2: 600px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
And later, add css rule as code below:
ul.pagination {
@include media-breakpoint-up(xs2, $grid-breakpoints-custom) {
li.pages-indicator {
display: inline-block;
}
}
}
SASS: Complete Code
Now you can have the complete code as below:
-
- themes/tutor-05/sass/css/_pagination.scss
- gitlab.com/…/sass/_pagination.scss.
@include media-breakpoint-up(md) {
.blog_previous {
span.page-link:after,
a.page-link:after {
content: " previous"
}
}
.blog_next {
span.page-link:before,
a.page-link:before {
content: "next "
}
}
}
$grid-breakpoints-custom: (
xs: 0,
xs2: 320px,
xs3: 400px,
xs4: 480px,
sm: 576px,
sm2: 600px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
ul.pagination {
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;
}
@include media-breakpoint-up(xs, $grid-breakpoints-custom) {
}
@include media-breakpoint-up(xs2, $grid-breakpoints-custom) {
li.pages-indicator {
display: inline-block;
}
}
@include media-breakpoint-up(xs3, $grid-breakpoints-custom) {
li.pagination--offset-1 {
display: inline-block;
}
}
@include media-breakpoint-up(xs4, $grid-breakpoints-custom) {
li.pagination--offset-2 {
display: inline-block;
}
}
@include media-breakpoint-up(sm, $grid-breakpoints-custom) {
li.first,
li.last,
li.pagination--offset-3 {
display: inline-block;
}
}
@include media-breakpoint-up(sm2, $grid-breakpoints-custom) {
li.pagination--offset-4 {
display: inline-block;
}
}
@include media-breakpoint-up(md, $grid-breakpoints-custom) {
li.pagination--offset-5,
li.pagination--offset-6 {
display: inline-block;
}
}
@include media-breakpoint-up(lg, $grid-breakpoints-custom) {
li.pagination--offset-7 {
display: inline-block;
}
}
@include media-breakpoint-up(xl, $grid-breakpoints-custom) {
}
}
5: Summary
You can have a look at our complete code here:
- themes/tutor-05/layouts/partials/pagination-responsive.html : gitlab.com/…/partials/pagination-responsive.html.
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.
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.
There are, some interesting topic about Pagination in Hugo. Consider continue reading [ Hugo - Pagination - Screen Reader ].
Thank you for reading.