8 KiB
title | description | categories | keywords | menu | weight | toc | aliases | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Pagination | Split a list page into two or more subsets. |
|
|
190 | true |
|
Displaying a large page collection on a list page is not user-friendly:
- A massive list can be intimidating and difficult to navigate. Users may get lost in the sheer volume of information.
- Large pages take longer to load, which can frustrate users and lead to them abandoning the site.
- Without any filtering or organization, finding a specific item becomes a tedious scrolling exercise.
Improve usability by paginating home
, section
, taxonomy
, and term
pages.
{{% note %}} The most common templating mistake related to pagination is invoking pagination more than once for a given list page. See the caching section below. {{% /note %}}
Terminology
- paginate
- To split a list page into two or more subsets.
- pagination
- The process of paginating a list page.
- pager
- Created during pagination, a pager contains a subset of a list page and navigation links to other pagers.
- paginator
- A collection of pagers.
Configuration
Control pagination behavior in your site configuration. These are the default settings:
{{< code-toggle file=hugo config=pagination />}}
- disableAliases
- (
bool
) Whether to disable alias generation for the first pager. Default isfalse
. - pagerSize
- (
int
) The number of pages per pager. Default is10
. - path
- (
string
) The segment of each pager URL indicating that the target page is a pager. Default ispage
.
With multilingual sites you can define the pagination behavior for each language:
{{< code-toggle file=hugo >}} [languages.en] contentDir = 'content/en' languageCode = 'en-US' languageDirection = 'ltr' languageName = 'English' weight = 1 [languages.en.pagination] disableAliases = true pagerSize = 10 path = 'page' [languages.de] contentDir = 'content/de' languageCode = 'de-DE' languageDirection = 'ltr' languageName = 'Deutsch' weight = 2 [languages.de.pagination] disableAliases = true pagerSize = 20 path = 'blatt' {{< /code-toggle >}}
Methods
To paginate a home
, section
, taxonomy
, or term
page, invoke either of these methods on the Page
object in the corresponding template:
The Paginate
method is more flexible, allowing you to:
- Paginate any page collection
- Filter, sort, and group the page collection
- Override the number of pages per pager as defined in your site configuration
By comparison, the Paginator
method paginates the page collection passed into the template, and you cannot override the number of pages per pager.
Examples
To paginate a list page using the Paginate
method:
{{ $pages := where site.RegularPages "Type" "posts" }}
{{ $paginator := .Paginate $pages.ByTitle 7 }}
{{ range $paginator.Pages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ end }}
{{ template "_internal/pagination.html" . }}
In the example above, we:
- Build a page collection
- Sort the page collection by title
- Paginate the page collection, with 7 pages per pager
- Range over the paginated page collection, rendering a link to each page
- Call the embedded pagination template to create navigation links between pagers
To paginate a list page using the Paginator
method:
{{ range .Paginator.Pages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ end }}
{{ template "_internal/pagination.html" . }}
In the example above, we:
- Paginate the page collection passed into the template, with the default number of pages per pager
- Range over the paginated page collection, rendering a link to each page
- Call the embedded pagination template to create navigation links between pagers
Caching
{{% note %}} The most common templating mistake related to pagination is invoking pagination more than once for a given list page. {{% /note %}}
Regardless of pagination method, the initial invocation is cached and cannot be changed. If you invoke pagination more than once for a given list page, subsequent invocations use the cached result. This means that subsequent invocations will not behave as written.
When paginating conditionally, do not use the compare.Conditional
function due to its eager evaluation of arguments. Use an if-else
construct instead.
Grouping
Use pagination with any of the grouping methods. For example:
{{ $pages := where site.RegularPages "Type" "posts" }}
{{ $paginator := .Paginate ($pages.GroupByDate "Jan 2006") }}
{{ range $paginator.PageGroups }}
<h2>{{ .Key }}</h2>
{{ range .Pages }}
<h3><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h3>
{{ end }}
{{ end }}
{{ template "_internal/pagination.html" . }}
Navigation
As shown in the examples above, the easiest way to add navigation between pagers is with Hugo's embedded pagination template:
{{ template "_internal/pagination.html" . }}
The embedded pagination template has two formats: default
and terse
. The above is equivalent to:
{{ template "_internal/pagination.html" (dict "page" . "format" "default") }}
The terse
format has fewer controls and page slots, consuming less space when styled as a horizontal list. To use the terse
format:
{{ template "_internal/pagination.html" (dict "page" . "format" "terse") }}
{{% note %}}
To override Hugo's embedded pagination template, copy the [source code] to a file with the same name in the layouts/partials directory, then call it from your templates using the partial
function:
{{ partial "pagination.html" . }}
[source code]: {{% eturl pagination %}} {{% /note %}}
Create custom navigation components using any of the Pager
methods:
{{< list-pages-in-section path=/methods/pager >}}
Structure
The example below depicts the published site structure when paginating a list page.
With this content:
content/
├── posts/
│ ├── _index.md
│ ├── post-1.md
│ ├── post-2.md
│ ├── post-3.md
│ └── post-4.md
└── _index.md
And this site configuration:
{{< code-toggle file=hugo >}} [pagination] disableAliases = false pagerSize = 2 path = 'page' {{< /code-toggle >}}
And this section template:
{{ range (.Paginate .Pages).Pages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ end }}
{{ template "_internal/pagination.html" . }}
The published site has this structure:
public/
├── posts/
│ ├── page/
│ │ ├── 1/
│ │ │ └── index.html <-- alias to public/posts/index.html
│ │ └── 2/
│ │ └── index.html
│ ├── post-1/
│ │ └── index.html
│ ├── post-2/
│ │ └── index.html
│ ├── post-3/
│ │ └── index.html
│ ├── post-4/
│ │ └── index.html
│ └── index.html
└── index.html
To disable alias generation for the first pager, change your site configuration:
{{< code-toggle file=hugo >}} [pagination] disableAliases = true pagerSize = 2 path = 'page' {{< /code-toggle >}}
Now the published site will have this structure:
public/
├── posts/
│ ├── page/
│ │ └── 2/
│ │ └── index.html
│ ├── post-1/
│ │ └── index.html
│ ├── post-2/
│ │ └── index.html
│ ├── post-3/
│ │ └── index.html
│ ├── post-4/
│ │ └── index.html
│ └── index.html
└── index.html