Bootstrap 4 Pagination + some added functionality

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">&laquo;&laquo;</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">&laquo;</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">&hellip;</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">&raquo;</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">&raquo;&raquo;</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
45%20PM

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
47%20PM

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 

43%20PM
26%20PM

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

8 Likes