A Table of Contents (ToC) gives readers a quick overview of the contents of a page and allows accessing specific parts quickly.
Being familiar with registering extensions in Kirby and a basic understanding of PHP will be useful.
To follow along, install a Kirby Starterkit, create a
/site/plugins/toc folder with an
index.php inside and add some headlines in a textarea field, for example in one of the subpages of the
Note that the techniques described here only work for fields that are rendered using the
kirbytext() method, usually a
textarea field (or plugin fields derived from this), not with the Editor.
To create a ToC, we need two things:
- Anchors in the text to which the ToC can link. While those could be added manually, it is much easier to auto-generate them from headlines. Anchors are useful even without a ToC, because you can link to these anchors from elsewhere.
- A navigation list of links to these anchors usually at the top of the page or the sidebar, the actual ToC.
Consequently, we have to implement two steps:
- Replace the headlines in the text with anchor headlines
- Add the ToC where we want it to appear
Let's start with replacing the headlines in our text with anchors.
We can replace headlines automatically with a
KirbyText hook or manually using a field method. The actual code to replace the headlines is the same, but we hook into different Kirby extensions.
Let's start with a
kirbytext:after hook that converts all given headline levels into anchors whenever the
kirbytext() method is called. We make the headline levels we want to convert configurable via a config option and use
h3 headlines as defaults.
Since we want to add a second hook of the same type in the next step, we use an array of functions after the
The important part here is the
preg_replace_callback() function. It needs three parameters…
- the search pattern (
- the callback function
- the input (
…and returns the modified string.
To include more headlines levels, you can set the
k-cookbook.toc.headlines option in the config:
If you now look at a page that contains headlines of the given level, you will see that the anchors were added.
This is an alternative to using the
kirbytext hook described above. Do not use the hook and this method in conjunction.
In your templates/snippets, you can now use the field method like this:
Instead of passing a string of options separated by
|, you can also pass an array of options:
If you don't pass an argument, the defaults will be used.
While the code we need to generate the ToCs from the headlines in a textarea field is the same, we can use different approaches to add them to the page.
- Use a placeholder that users can manually put into a textarea field where they want the ToC to appear
- Add a ToC in our template code using a field method
We will look into both options in this recipe.
To keep it simple, we will include only one headline level in our ToC. We will cover multiple levels in a future recipe.
toc placeholder, we use another
kirbytext:after hook, and a snippet that will contain the HTML for the ToC. We will reuse this snippet for the alternative field method approach below.
The code for the snippet goes into
If you now add a
(toc) placeholder to a page that contains headlines of the given level, you should see a ToC appear where you added the placeholder.
The field method returns a collection of headline objects.
In your templates, you can now use the
headlines() field method in conjunction with the snippet we registered above.
In this recipe we explored different ways to add anchor headlines and a ToC to pages.
You can also mix the hook that auto-generates anchor headlines with the
headlines field method and the
toc.php snippet to create the ToC in your templates rather than through a placeholder users add manually.
If you vote for generating the ToC via the field method in your templates, you can still give editor control whether to show a ToC on a page by page basis using a toggle or checkbox field in your blueprints, for example:
You could also only show the ToC if there is at least a given number of headlines by slightly modifying the
toc.php snippet, for example, if there are at least 3 headlines:
If you are using the blocks or layouts fields with separate blocks for your headings, you can filter the blocks by type
heading and heading level:
Then create the ToC snippet like this:
The last step is to overwrite the default heading block snippet and add an