Skip to content

Instantly share code, notes, and snippets.

@rordi
Last active April 18, 2021 18:33
Show Gist options
  • Save rordi/eab8606b377638eeaa984367bde0a2d0 to your computer and use it in GitHub Desktop.
Save rordi/eab8606b377638eeaa984367bde0a2d0 to your computer and use it in GitHub Desktop.
Previous / Next Navigation in Hugo with custom section order

Previous/Next navigation in Hugo with custom order based on param / attribute

This gist let's you return previous/next pages based on a frontmatter parameter in Hugo. In this exmaple, the frontmatter parameter is called position, where lower positions come first.

This prev / next navigation is looping: if there is no "next >" entry anymore, the first entry of the collection will be linked. Same for "< prev": if there is no previous element, the last element of the collection will be linked.

<div class="nav-prev-next">
    {{ $currentSection := (($.Site.GetPage "section" .Section).Pages.ByParam "position") }}

    {{ $.Scratch.Set "counter" 0 }}
    {{ $.Scratch.Set "currentPosition" 0 }}

    {{/* calculate current position in array */}}
    {{ range $currentSection }}
        {{ if eq $.Permalink .Permalink }}
            {{ $.Scratch.Set "currentPosition" ($.Scratch.Get "counter") }}
        {{ end }}
        {{ $.Scratch.Set "counter" (add ($.Scratch.Get "counter") 1) }}
    {{ end }}


    {{/* get Permalink for element before and after current position in array */}}
    {{ $.Scratch.Set "counter" 0 }}
    {{ range $currentSection }}
        {{/* next is at current position + 1 */}}
        {{ if eq ($.Scratch.Get "counter") (add ($.Scratch.Get "currentPosition") 1) }}
            {{ $.Scratch.Set "next" .Permalink }}
        {{ end }}

        {{/* prev is at current position - 1 */}}
        {{ if eq ($.Scratch.Get "counter") (sub ($.Scratch.Get "currentPosition") 1) }}
            {{ $.Scratch.Set "previous" .Permalink }}
        {{ end }}

        {{ $.Scratch.Set "counter" (add ($.Scratch.Get "counter") 1) }}
    {{ end }}
    
    
    {{/* prints the '< prev' link - remove the else block if you do not want to link the last entry if there is no previous entry */}}
    {{ if $.Scratch.Get "previous" }}
        <a href="{{ $.Scratch.Get "previous" }}" class="nowrap nav-prev" aria-label="Previous entry">
	        <img src="/images/uploads/angle.svg" alt="Previous entry" />
	    </a>
    {{ else }}
        {{range last 1 $currentSection }}
            <a href="{{ .Permalink }}" class="nowrap nav-prev" aria-label="Previous entry">
	            <img src="/images/uploads/angle.svg" alt="Previous entry" />
            </a>
        {{ end }}
    {{ end }}


    {{/* print the 'next >' link - remove the else block if you do not want to link the first entry if there is no next entry */}}
    {{ if $.Scratch.Get "next" }}
        <a href="{{ $.Scratch.Get "next" }}" class="nowrap nav-next" aria-label="Next entry">
	        <img src="/images/uploads/angle.svg" alt="Next entry" />
        </a>
    {{ else }}
        {{ range first 1 $currentSection }}
            <a href="{{ .Permalink }}" class="nowrap nav-next" aria-label="Next entry">
	            <img src="/images/uploads/angle.svg" alt="Next entry" />
            </a>
        {{ end }}
    {{ end }}
</div>
@cmmartti
Copy link

Here's a simplified solution using the front matter parameter chapter, without looping:

{{- $pages := ($.Site.GetPage "section" .Section).Pages.ByParam "chapter" }}
{{- $.Scratch.Set "curPosition" 0 }}
{{- $.Scratch.Set "index" 0 }}
{{- range $pages }}
  {{- if eq $ . }}
    {{- $.Scratch.Set "curPosition" ($.Scratch.Get "index") }}
  {{- end }}
  {{- $.Scratch.Add "index" 1 }}
{{- end }}
{{- $next := (index $pages (add ($.Scratch.Get "curPosition") 1)) }}
{{- $prev := (index $pages (sub ($.Scratch.Get "curPosition") 1)) }}

{{- with $prev }}
<a href="{{ .Permalink }}">← {{ .Params.chapter }}. {{ .Title }}</a>
{{- end }}

{{- with $next }}
<a href="{{ .Permalink }}">{{ .Params.chapter }}. {{ .Title }} →</a>
{{- end }}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment