Skip to main content

Reading time: five minutes. This page is the honest list of what the plugin does not do, and of the places where the answer is “it depends”. We would rather you read it here than find out on your own site.

When no list appears at all

A list is left out, on purpose, when any of these is true:

  • The post has fewer headings than the minimum. Three by default. A list of two entries is noise.
  • Every heading is at a level you are not listing. h2 and h3 by default, so a post written entirely in h4 gets nothing. Tick h4 in the settings, or raise the headings a level.
  • The post’s own panel says no. Check the Table of Contents panel in the editor.
  • The kind of content is not ticked. Posts and pages by default. Products, documentation, recipes and anything else your site has must be ticked in Which content gets a list.
  • Automatic placement is off and there is no block, shortcode or widget on the page.
  • Hide on phones is on and you are looking on a phone.

h1 is never listed

Your post’s title is an h1, and a contents list that begins with the title of the thing you are already reading is a wasted line. So h1 is never listed, however your theme marks the title up, and whether or not the h1 is inside the content.

If your post genuinely uses h1 for its sections, which some older content does, the honest fix is to change those to h2. It is better for search engines and for screen readers too.

Headings the plugin cannot see

The plugin reads the post’s content. It does not read the rest of the page. So a heading is invisible to it if it is:

  • In your theme’s template rather than in the post. A page title, a section heading your theme prints, a heading in a footer or a sidebar.
  • In a custom field that your theme renders separately from the content.
  • Added by a plugin after ours has run. We run late, at priority 100 on the_content, so almost everything is already in place; but something running later still arrives after us.
  • Inside <pre> or <code>. Deliberate: a tutorial that shows HTML should not list that example’s headings.

This matters most with page builders, which often build a page out of their own widgets rather than out of post content. Themes and page builders covers what to do, and the short answer is to place the list with the shortcode where the builder can see it.

Archive, category, search and front pages

No list, and no anchors either, on any page that shows more than one post. A contents list for one of ten posts on a page would be meaningless, and ten contents lists would be worse. If a page shows a single post in full, that post gets its list as usual.

The plugin keeps a link working when you reword a heading, move it, or change its level. It cannot keep one working when you delete the section, because there is nowhere honest for that link to go. The reader lands at the top of the post, which is what every other plugin does for every edit.

This is the one setting that can do real damage. Every link anybody has ever shared to a heading on your site contains the anchor as it was at the time. Change the format and all of them point at names that no longer exist.

So: choose the format when you set the plugin up, or let the move from your old plugin choose it, and then leave it alone. The setting says as much on the page itself.

Two headings with the same words

The second one gets -2 after it, the third -3, and the first is left alone. That is what WordPress does and what readers expect. With Keep anchors when a heading is edited on, which of your repeated headings is which stays settled: the first one keeps the plain anchor even if you add another above it later.

Headings with no words left

A heading made only of punctuation, or an emoji, or an image with no text, has nothing to make a name out of. It gets section, then section-2 for the next one, and so on. The list still shows whatever the heading contains.

Scripts other than Latin

Anchors keep the words of the heading whatever the script: Japanese, Greek, Russian, Arabic and Hebrew all give anchors made of their own letters, which is what WordPress does for a permalink. Accented Latin letters are folded, so “Café” becomes “cafe”, because that is what people expect from a web address.

If you are moving from another plugin, the move keeps whatever that plugin was producing, which may be different. That is the point of it.

Very long posts

There is no limit, and the work is proportional to the number of headings rather than the length of the post. A post with 200 headings and 22,000 words takes about three milliseconds to read, measured on PHP 7.4.

Two things about very long lists, though, which are judgement rather than engineering. A list of 60 entries fills a phone screen and is harder to use than a list of 10, so consider listing h2 only. And a list that starts folded away is close to no list at all, because most readers never open one.

Right to left

Arabic and Hebrew mirror from the same stylesheet, with nothing to set: the indentation, the numbers and the fold arrow all move to the other side. We test this on every theme in our matrix, which is how we found that two popular themes indent lists in a way that fought with ours.

What the free plugin does not have

Four things, deliberately, because all four need JavaScript on the front end and the plugin’s whole claim is that it sends none:

  • the heading you are currently reading highlighted in the list;
  • a list that stays on screen as you scroll;
  • a reading-progress line;
  • a floating contents button on phones.

They are in the Pro version, which loads a small script only on pages that use them. Nothing in the free plugin changes when you add it.

What we have no plans to build

Said plainly so you are not waiting for it: schema or sitemap output from the list, a contents list for archive or category pages, a list built from several posts at once, anchors on things that are not headings, a different title per heading, and any kind of admin notice.

What next