PHPackages                             craftsnippets/table-of-contents - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. craftsnippets/table-of-contents

ActiveCraft-plugin[Utility &amp; Helpers](/categories/utility)

craftsnippets/table-of-contents
===============================

This plugin generates a table of contents from HTML headers in text.

3.0.0(2y ago)44.2k[6 issues](https://github.com/craft-snippets/craft-table-of-contents/issues)MITPHP

Since Jun 30Pushed 2y ago1 watchersCompare

[ Source](https://github.com/craft-snippets/craft-table-of-contents)[ Packagist](https://packagist.org/packages/craftsnippets/table-of-contents)[ RSS](/packages/craftsnippets-table-of-contents/feed)WikiDiscussions craft-5 Synced 3w ago

READMEChangelog (5)Dependencies (1)Versions (7)Used By (0)

Table of contents plugin for Craft CMS 3.x
==========================================

[](#table-of-contents-plugin-for-craft-cms-3x)

This plugin generates a table of contents from HTML headers in text. Anchor links in table direct to corresponding headers in text.

Table of contents can be nested - nesting level will be based on header level.

Here's screenshot of example table of contents generated by plugin:

[![Screenshot](resources/img/example.PNG)](resources/img/example.PNG)

Requirements
------------

[](#requirements)

This plugin requires Craft CMS 3.0.0-beta.23 or later.

It also requires [Anchors plugin](https://plugins.craftcms.com/anchors), since it makes use of its internal functions.

Installation
------------

[](#installation)

You can install this plugin from the Plugin Store or with Composer.

To install plugin with composer, run following command:

```
composer require craftsnippets/table-of-contents
```

Then in the control panel go to settings, plugins - and click "install" next to "table of contents".

Usage
-----

[](#usage)

To create the table of contents, you need to pass HTML containing headers to `craft.toc.getLinks` function and output returned data using `{% nav %}` Twig tag.

Don't forget to also put your HTML through `anhors` filter provided by Anchors plugin - it will add `id` attribute to headers, so anchor links inside the table of contents have something to direct to.

Remember to use `anchors` filter **after** passing HTML to `getLinks` function. Otherwise, links in table of contents would contain escaped HTML content of links that were added to headers by Anchors plugin.

```
{% set text %}
some text with headers...
{% endset %}

{% set table = craft.toc.getLinks(text) %}

    {% nav link in table %}

            {{ link.text }}
            {% ifchildren %}

                    {% children %}

            {% endifchildren %}

    {% endnav %}

{{text|anchors}}

```

Don't forget to give each of your links bit of left margin to show their hierarchy.

```
li{
  margin-left: 1rem;
}

```

Nested numeric list
-------------------

[](#nested-numeric-list)

To display numeric count before links within the table of contents, you can use bit of CSS. This will work also for nested lists.

```
ul {
  counter-reset: section;
  list-style-type: none;
}
li::before {
  counter-increment: section;
  content: counters(section, ".") " ";
}

```

Alternative header tags
-----------------------

[](#alternative-header-tags)

By default, Table of contents plugin searches for `h1`, `h2` and `h3` tags. Just like in Anchors plugin, this can be overwritten by passing the second argument to `getLinks` function.

```
{% table = craft.toc.getLinks(text, 'header1,header2,header3') %}

```

Don't forget to do the same when using `anchors` filter.

non-ASCII characters mapping
----------------------------

[](#non-ascii-characters-mapping)

The third parameter of `getLinks()` method can be used to change non-ASCII character used to generate link hashes, just like with the anchors plugin. Here's a quote from anchors plugin documentation:

> The anchors filter will convert any non-ASCII characters to ASCII, using the current site’s language’s ASCII character mappings by default. If you are displaying content in a different language than the current site, use the language argument to override which ASCII character mappings should be used.

Here's the example usage:

```
{% set tableOfContents = craft.toc.getLinks(html, 'h1,h2,h3', entry.site.language) %}

```

Stripping tags from links text
------------------------------

[](#stripping-tags-from-links-text)

If headers which are converted to links contain some html tags inside them, links within table of contents will contain these tags too. You can disable this by setting fourth parameter of `getLinks()` method to `true`.

```
{% set tableOfContents = craft.toc.getLinks(html, 'h1,h2,h3', null, true) %}

```

Smooth scrolling
----------------

[](#smooth-scrolling)

You can achieve smooth scrolling effect with single CSS property.

```
html{
   scroll-behavior: smooth;
}

```

Unfortunetly it does not wok on Safari or IE - see more on [caniuse](https://caniuse.com/#search=scroll-behavior).

Same effect that works in all modern browsers can be achieved with this jQuery code:

```
  $('.table-of-contents a').on('click', function(event) {
    var hash = '#' + $(this).attr('href').split('#')[1]
    var element = $(hash)
    if (element.length) {
      event.preventDefault();
      history.pushState(hash, undefined, hash)
      $('html, body').animate({scrollTop: element.offset().top}, 500)
    }
  });

  window.addEventListener('popstate', function(e) {
    if(e.state && e.state.startsWith('#') && $(e.state).length){
      $('html, body').animate({scrollTop: $(e.state).offset().top}, 500)
    }
  });

  $('html, body').on("scroll mousedown wheel DOMMouseScroll mousewheel keyup touchmove", function(){
    $('html, body').stop();
  });

```

If a user start to scroll (using mouse scroll wheel) during an animation, scrolling will be canceled to avoid "fighting" with it.

Despite animation replacing `click` event, hash will still be appended to URL and browser back or forward buttons will work - thanks to use of JavaScript history API.

---

Icon made by [Dave Gandy](https://www.flaticon.com/authors/dave-gandy) from [www.flaticon.com](https://www.flaticon.com/).

---

Brought to you by [Piotr Pogorzelski](http://craftsnippets.com)

###  Health Score

27

—

LowBetter than 47% of packages

Maintenance0

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~434 days

Total

5

Last Release

816d ago

Major Versions

1.0.2 → 2.0.02022-05-28

2.0.1 → 3.0.02024-04-02

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/42622545?v=4)[Piotr Pogorzelski](/maintainers/piotrpog)[@piotrpog](https://github.com/piotrpog)

---

Top Contributors

[![piotrpog](https://avatars.githubusercontent.com/u/42622545?v=4)](https://github.com/piotrpog "piotrpog (25 commits)")

---

Tags

craftcmstable-of-contentscraft cms

### Embed Badge

![Health badge](/badges/craftsnippets-table-of-contents/health.svg)

```
[![Health](https://phpackages.com/badges/craftsnippets-table-of-contents/health.svg)](https://phpackages.com/packages/craftsnippets-table-of-contents)
```

###  Alternatives

[spicyweb/craft-neo

A Matrix-like field type with block hierarchy

393808.8k10](/packages/spicyweb-craft-neo)[craftcms/feed-me

Import content from XML, RSS, CSV or JSON feeds into entries, categories, Craft Commerce products, and more.

292943.4k27](/packages/craftcms-feed-me)[verbb/formie

The most user-friendly forms plugin for Craft.

100387.6k57](/packages/verbb-formie)[verbb/navigation

Create navigation menus for your site.

92698.4k18](/packages/verbb-navigation)[verbb/workflow

Enforce multi-step review processes for creating entries.

138123.0k1](/packages/verbb-workflow)[verbb/comments

Add comments to your site.

13753.7k](/packages/verbb-comments)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
