I modified the existing internal pagination template to support bootstrap 4’s pagination. I also added some additional customization features which I thought were needed.
First here is the optional config.toml
settings
Everything is commented out since no settings are required and the output will be the same as the internal template but in BS4 format.
[params.pagination]
# These are all optional and default to true
# class = "pagination-lg justify-content-center" # Add classes to the nav element
# showBeginEnd = true # If false it will hide the First/Previous/Next/Last if it evaluates to false
# showFirst = true # If false it will hide the First page nav button
# firstIndicator = "" # Change the default indicator to something else, like "First" or an icon wrapped in an i element
# showPrevious = true # If false it will hide the previous button
# previousIndicator = "" # Change the default indicator to something else, like "Previous" or an icon wrapped in an i element
# showNext = true # True by default - Only "false" will hide the next button
# nextIndicator = "" # Change the default indicator to something else, like "Next" or an icon wrapped in an i element
# showLast = true
# lastIndicator = ""
# showPageNumbers = true # If false it will hide the numbering of pages
# pagesBetweenActive = 2 # How many page numbers to show between the active page - it defaults to 3
Here is the partial
{{ $pag := $.Paginator }}
{{ if gt $pag.TotalPages 1 }}
<nav class="{{ .Section }}-pagination" aria-label="{{ .Section }} navigation">
<ul class="pagination {{- with .Params.pagination.class | default .Site.Params.pagination.class }} {{ . }} {{- end }}">
{{ if (and (not $pag.HasPrev) (eq $.Site.Params.pagination.showBeginEnd false)) }}
{{ else }}
{{ if not (eq .Site.Params.pagination.showFirst false) }}
{{ with $pag.First }}
<li class="page-item page-item-first">
<a class="page-link" href="{{ .URL }}" aria-label="First">{{ with $.Site.Params.pagination.firstIndicator }} {{ . | markdownify }} {{else}}<span aria-hidden="true">««</span><span class="sr-only">First</span>{{end}}</a>
</li>
{{ end }}
{{ end }}
{{ if not (eq .Site.Params.pagination.showPrevious false) }}
<li class="page-item page-item-previous {{- if not $pag.HasPrev }} disabled {{- end }}">
<a class="page-link" href="{{ if $pag.HasPrev }}{{ $pag.Prev.URL }}{{ end }}" aria-label="Previous" tabindex="-1">{{ with $.Site.Params.pagination.previousIndicator }} {{ . | markdownify }} {{else}}<span aria-hidden="true">«</span><span class="sr-only">Previous</span>{{end}}</a>
</li>
{{ end }}
{{ end }}
{{ $.Scratch.Set "__paginator.ellipsed" false }}
{{ if not (eq .Site.Params.pagination.showPageNumbers false) }}
{{ range $pag.Pagers }}
{{ $right := sub .TotalPages .PageNumber }}
{{ $showNumber := or (le .PageNumber 1) (eq $right 0) }}
{{ $showNumber := or $showNumber (and (gt .PageNumber (sub $pag.PageNumber ( $.Site.Params.pagination.pagesBetweenActive | default 3 ))) (lt .PageNumber (add $pag.PageNumber ( $.Site.Params.pagination.pagesBetweenActive | default 3 )))) }}
{{ if $showNumber }}
{{ $.Scratch.Set "__paginator.ellipsed" false }}
{{ $.Scratch.Set "__paginator.shouldEllipse" false }}
{{ else }}
{{ $.Scratch.Set "__paginator.shouldEllipse" (not ($.Scratch.Get "__paginator.ellipsed") ) }}
{{ $.Scratch.Set "__paginator.ellipsed" true }}
{{ end }}
{{ if $showNumber }}
<li class="page-item page-item-number {{- if eq . $pag }} active {{- end }}">
<a class="page-link" href="{{ .URL }}">{{ .PageNumber }} <span class="sr-only">(current)</span></a>
</li>
{{ else if ($.Scratch.Get "__paginator.shouldEllipse") }}
<li class="page-item page-item-ellipse disabled"><span aria-hidden="true">…</span></li>
{{ end }}
{{ end }}
{{ end }}
{{ if (and (not $pag.HasNext ) (eq $.Site.Params.pagination.showBeginEnd false)) }}
{{ else }}
{{ if not (eq .Site.Params.pagination.showNext false) }}
<li class="page-item page-item-next {{- if not $pag.HasNext }} disabled {{- end }}">
<a class="page-link" href="{{ if $pag.HasNext }}{{ $pag.Next.URL }}{{ end }}" aria-label="Next">{{ with $.Site.Params.pagination.nextIndicator }} {{ . | markdownify }} {{else}}<span aria-hidden="true">»</span><span class="sr-only">Next</span>{{end}}</a>
</li>
{{ end }}
{{ if not (eq .Site.Params.pagination.showLast false) }}
{{ with $pag.Last }}
<li class="page-item page-item-last">
<a class="page-link" href="{{ .URL }}" aria-label="Last">{{ with $.Site.Params.pagination.lastIndicator }} {{ . | markdownify }} {{else}}<span aria-hidden="true">»»</span><span class="sr-only">Last</span>{{end}}</a>
</li>
{{ end }}
{{ end }}
{{ end }}
</ul>
</nav>
{{ end }}
Another addition is labeling of the items for easier CSS styling
Eg.
// This is css styling for the page numbers
.pagination > .page-item-number.active > a {
background-color: #2d8eff;
border-color: #2d8eff;
color: #fff;
}
// CSS selectors
// These are on the li elements so may need to add the child a element to the css selector for desired result (see above)
.page-item-first {}
.page-item-previous {}
.page-item-number {}
.page-item-ellipse {}
.page-item-next {}
.page-item-last {}
So with no customization the pagination would output
With the following settings
Note: I’m using material icons for the icons
[params.pagination]
# These are all optional and default to true
class = "pagination-lg justify-content-center" # Add classes to the nav element
showBeginEnd = true # If false it will hide the First/Previous/Next/Last if it evaluates to false
showFirst = true # If false it will hide the First page nav button
firstIndicator = "<i class='material-icons'>chevron_left</i>" # Change the default indicator to something else, like "First" or an icon wrapped in an i element
showPrevious = true # If false it will hide the previous button
previousIndicator = "Previous" # Change the default indicator to something else, like "Previous" or an icon wrapped in an i element
showNext = true # True by default - Only "false" will hide the next button
nextIndicator = "Next" # Change the default indicator to something else, like "Next" or an icon wrapped in an i element
showLast = true
lastIndicator = "<i class='material-icons'>chevron_right</i>"
showPageNumbers = true # If false it will hide the numbering of pages
pagesBetweenActive = 2 # Shows how many page numbers to show between the active page - it defaults to 3
This outputs
And an example how the hiding the beginning and end looks when it’s either on page 1 or the last page
[params.pagination]
showBeginEnd = false
Hope this is useful to you guys!
Edit: Forgot to mention I also added {{ .Section }}
to the nav element for easier css styling between pages if that’s something you wanted to do.
Edit 2: Added more aria declarations and added a class
param for the ul
wrapper so you can do things like justify-content-center
etc. This class can be declared globally in the config.toml
file or by page through the front-matter using .Params.pagination.class