Splitting a long page
Some pages get long enough that a reader loses their place in them. A marker in the body splits one source file into several pages, each with its own URL, and hands your layout the pieces to draw links from.
Nothing else about the page changes. There is no pagination block to write, no permalink to set, and no second file.
What you will build
- One Markdown file rendering as three pages, at
/guide/,/guide/2/and/guide/3/. - Named parts rather than numbered ones.
- A navigation partial that renders on split pages and disappears everywhere else.
Split the page
Take any long page and drop a marker where the break belongs:
---
title: 'A long guide'
slug: 'guide'
---
The opening section.
<!--pagebreak-->
The second section.
<!--pagebreak-->
The third section.
Run npm start and the one file is now three pages. Part one keeps the URL the page already had; the rest are numbered underneath it:
/guide/ /guide/2/ /guide/3/
The marker goes in the body, not the front matter. It is an HTML comment, so it stays invisible in any Markdown preview that has not heard of it.
Name the parts
Numbers work and cost nothing to translate, but names read better in a nav. The grammar is the wikilink one, so | gives a label and # gives an anchor:
<!--pagebreak|Data files-->
<!--pagebreak#setup|Verify it works-->
A label names the part that follows the marker. That is worth holding onto, because it makes "Next page" a bad label and "Data files" a good one: you are naming a destination, not a direction.
Part one is the exception. No marker precedes it, so it can never carry a label and always reports '1'. If your nav names the other parts, give the first one a name in the template.
Render the navigation
Baseline splits the page and stops there. It emits no markup of its own, the same way it hands you page.translations and lets you decide what a language switcher looks like.
A split page carries _pagebreak; every other page has nothing there, so one guard covers the whole site. Create src/_includes/components/page-parts.njk:
{%- if _pagebreak %}
<nav aria-label="Page parts">
<span>Page {{ _pagebreak.number }} of {{ _pagebreak.total }}</span>
<ol>
{%- for part in _pagebreak.parts %}
<li>
{%- set label = "Introduction" if part.number == 1 else part.label %}
{%- if part.current %}
<span aria-current="page">{{ label }}</span>
{%- else %}
<a href="{{ part.url }}{% if part.anchor %}#{{ part.anchor }}{% endif %}">{{ label }}</a>
{%- endif %}
</li>
{%- endfor %}
</ol>
</nav>
{%- endif %}
Include it in your layout after the content, and it renders on the pages that were split and nowhere else:
{{ content | safe }}
{%- include "components/page-parts.njk" %}
aria-current="page" on the part you are reading is what tells a screen reader which one it is on. The {% set label %} line is the part-one workaround from above.
Check what came out
Reload and click through. Three things are worth confirming:
Each part is its own page with its own <head>, canonical and title. They share the title and description, which is fine: Google does not ask paginated pages for distinct ones, and each part canonicalises to itself.
Only part one appears in a collection, so a posts list shows the page once rather than three times.
A wikilink to the page lands on part one, because every part inherits the same slug and the first registration wins.
What Baseline will not split
Three cases, each one leaving the page whole rather than splitting it badly:
- A page that already paginates. Two pagination configs cannot share a template, and yours is the one you asked for.
- A page that sets
eleventyComputed.permalink. Computed data resolves last and would discard the numbering, collapsing every part onto one URL. - A page with
permalink: false. Nothing is written, so there is nothing to split.
A permalink function is fine and is the common case. Baseline calls yours and numbers the parts under whatever it returns.
One trap worth knowing if you write about the marker rather than with it: a Nunjucks raw block will not protect it. The split happens before Nunjucks runs, so a marker inside a raw block still splits the page and leaves both halves with an unbalanced tag. A fenced code block does protect it, which is how the examples above survive on this page.
Next steps
- Content helpers for the marker grammar in full, next to the rest of the Markdown syntax Baseline adds.
- Globals for the
_pagebreakshape your template reads. - Content organisation for where a long page sits in a content tree in the first place.