Table of Contents Plus

A powerful yet user friendly plugin that automatically creates a context specific index or table of contents (TOC) for long pages (and custom post types). More than just a table of contents plugin, this plugin can also output a sitemap listing pages and/or categories across your entire site.


Built from the ground up and with Wikipedia in mind, the table of contents by default appears before the first heading on a page. This allows the author to insert lead-in content that may summarise or introduce the rest of the page. It also uses a unique numbering scheme that doesn’t get lost through CSS differences across themes.

This plugin is a great companion for content rich sites such as content management system oriented configurations. That said, bloggers also have the same benefits when writing long structured articles. Discover how Google uses this index to provide ‘Jump To’ links to your content.

Includes an administration options panel where you can customise settings like display position, define the minimum number of headings before an index is displayed, other appearance, and more. For power users, expand the advanced options to further tweak its behaviour – eg: exclude undesired heading levels like h5 and h6 from being included; disable the output of the included CSS file; adjust the top offset and more. Using shortcodes, you can override default behaviour such as special exclusions on a specific page or even to hide the table of contents altogether.

Prefer to include the index in the sidebar? Go to Appearance > Widgets and drag the TOC+ to your desired sidebar and position.

Custom post types are supported, however, auto insertion works only when the_content() has been used by the custom post type. Each post type will appear in the options panel, so enable the ones you want.


Install / upgrade

Install the plugin by searching for Table of Contents Plus from the plugin add menu, or directly from the WordPress plugins repository.

There are no special upgrade instructions (woohoo!). Overwrite your existing folder with the latest or use the streamlined approach in the plugin menu. Your options will not be lost.


The simplest approach

For the impatient, all you have to do is enable the plugin.

The plugin will apply default settings and produce the table of contents before the first heading on pages (not posts, nor custom post types) with four or more headings.

No shortcodes are needed.

Where’s my table of contents?

  1. In most cases, the post, page or custom post type has less than the minimum number of headings. By default, this is set to four so make sure you have at least four headings within your content. If you want to change this value, you can find it under ‘Main Options’ > ‘Show when’.
  2. Is auto insertion enabled for your content type? By default, only pages are enabled.
  3. Have you got [ no_toc ] somewhere within the content? This will disable the index for the current post, page or custom post type.
  4. If you are using the TOC+ widget, check if you have the “Show the table of contents only in the sidebar” enabled as this will limit its display to only the sidebar. You can check by going into Appearance > Widgets.
  5. You may have restricted generation to a URL path match. The setting can be found in the advanced section under Main Options.

How do I stop the table of contents from appearing on a single page?

Place the following [ no_toc ] anywhere on the page to suppress the table of contents. This is known as a shortcode and works for posts, pages and custom post types that make use of the_content()

I’ve set wrapping to left or right but the headings don’t wrap around the table of contents

This normally occurs when there is a CSS clear directive in or around the heading originating from the theme (Twenty Eleven and Twenty Twelve are two themes which do this). This directive tells the user agent to reset the previous wrapping specifications.

You can adjust your theme’s CSS or try moving the table of contents position to the top of the page. If you didn’t build your theme, I’d highly suggest you try the Custom CSS plugin if you wish to make CSS changes.

Try adding the following CSS to allow the wrapping to occur around the table of contents:
h1, h2, h3, h4, h5, h6 { clear: none; }

How do I include the name of the page in the table of contents title?

As the title of the page changes depending on the page you’re viewing, you can use the following special variable to automatically insert the title of the page into the table of contents heading:


You can use it as is or place text either side of the variable.

As an example: if your page is named Great Expectations and your table of contents title is set to Contents for %PAGE_NAME%, the final title would read Contents for Great Expectations

My site has 100 pages but I only want the table of contents to appear on 10 of them

You could put [ no_toc ] on the 90 pages but that wouldn’t be fun… so try the following:

  1. Go to Settings > TOC+ and disable the auto insertion option for pages (or the content type you’re working with).
  2. Add [ toc ] onto the 10 pages that need them. Note that the table of contents will appear where you placed the shortcode.

Alternatively, you could also experiment with the restrict path option if the pages you want to include the index on all fall within a certain section of your site (eg /doc/).

I want to ignore certain headings

Use the ‘exclude headings’ option if you would like to ignore certain headings. Separate multiple headings with a pipe |. Use an asterisk * as a wildcard to match other text. Note that this is not case sensitive. Some examples include:

  • Fruit* ignore headings starting with Fruit
  • *Fruit Diet* ignore headings with Fruit Diet somewhere in the heading
  • Apple Tree|Oranges|Yellow Bananas ignore headings that are exactly Apple Tree, Oranges or Yellow Bananas

Can I have the table of contents in the sidebar?

Use the TOC+ widget and drag it into your desired position. If you want the table of contents to only be displayed in the sidebar, then make sure you tick that option in the widget.

Unlike Wikipedia, I want all my anchors to be lowercase and use hyphens rather than underscores

There are two options that allow you to adjust the casing and use of hyphens. If you still require more, you can massage it a little more by attaching into the toc_url_anchor_target filter. See the developers section for an example.

I would like to incorporate a sitemap

  1. Create a page for your sitemap (if you have an existing one, use that instead).
  2. Add [ sitemap ] into your page and save.

The above is the simplest example of integrating a sitemap listing all pages and categories. You can customise the sitemap options under Settings > TOC+ or check out some of the more advanced uses with the sitemap related shortcodes below.

You could also incorporate a sitemap using a text widget and pasting any of the sitemap shortcodes.

The sitemap uses a strange font dissimilar to the rest of the site

No extra styles are created for the sitemap, instead it inherits any styles you used when adding the shortcode. If you copy and pasted, you probably also copied the ‘code’ tags surrounding it so remove them if this is the case.

In most cases, try to have the shortcode on its own line with nothing before or after the square brackets.


The plugin was designed to be as seamless and painfree as possible and did not require you to insert a shortcode for operation. However, using the shortcode allows you to fully control the position of the table of contents within your page. The following shortcodes are available with this plugin.

When parameters are left out for the shortcodes below, they will fallback to the settings you defined under Settings > TOC+.

[ toc ]Lets you generate the table of contents at the preferred position. Also useful for sites that only require a TOC on a small handful of pages.
  • label: text, title of the table of contents
  • no_label: true/false, shows or hides the title
  • wrapping: text, either “left” or “right”
  • heading_levels: numbers, this lets you select the heading levels you want included in the table of contents. Separate multiple levels with a comma. Example: include headings 3, 4 and 5 but exclude the others with heading_levels="3,4,5"
  • exclude: text, enter headings to be excluded. Separate multiple headings with a pipe |. Use an asterisk * as a wildcard to match other text. You could also use regular expressions for more advanced matching.
  • class: text, enter CSS classes to be added to the container. Separate multiple classes with a space.
[ no_toc ]Allows you to disable the table of contents for the current post, page, or custom post type. 
[ sitemap ]Produces a listing of all pages and categories for your site. You can use this on any post, page or even in a text widget. 
[ sitemap_pages ]Lets you print out a listing of only pages.
  • heading: number between 1 and 6, defines which html heading to use
  • label: text, title of the list
  • no_label: true/false, shows or hides the list heading
  • exclude: IDs of the pages or categories you wish to exclude
  • exclude_tree: ID of the page or category you wish to exclude including its all descendants
[ sitemap_categories ]Similar to [ sitemap_pages ] but for categories. 
[ sitemap_posts ]This lets you print out an index of all published posts on your site. By default, posts are listed in alphabetical order grouped by their first letters. There are CSS classes for each section, letter and list allowing you to customise the appearance.
  • order: text, either ASC or DESC
  • orderby: text, popular options include “title”, “date”, “ID”, and “rand”. See WP_Query for a list.
  • separate: true/false (defaults to true), does not separate the lists by first letter when set to false.

For developers

How do I customise my anchors?

If you’re still not happy with the anchors, you can modify them to suit your needs through a custom function hooked into the toc_url_anchor_target filter. As an example, place the below code snippet into your functions.php file to convert all anchors to uppercase.

function my_custom_anchor( $anchor )
	return strtoupper( $anchor );
add_filter( 'toc_url_anchor_target', 'my_custom_anchor' );

toc_get_index( $content = ”, $prefix_url = ” )

Returns a HTML formatted string of the table of contents without the surrounding UL or OL tags to allow the theme editor to supply their own ID and/or classes to the outer list.

Both parameters are optional:

  • $content is the entire content with headings. If blank, will default to the current content found in $post (eg within “the loop”).
  • $prefix_url is the URL to prefix the anchor with. If a string was provided, it will be used as is. If set to “true” then will try to obtain the permalink from the $post object.

These examples assume you are within “the loop”:

  1. Obtain the index for the current page
    echo '<ul id="my_toc">' . toc_get_index() . '</ul>';
  2. Create a listing of all children and their headings
    $children = new WP_Query(array(
    	'post_parent' => get_the_ID(),
    	'posts_per_page' => -1	// get all children
    while ( $children->have_posts() ) {
    		'<h3>' . get_the_title() . '</h3>' .
    		'<ul>' . toc_get_index( get_the_content(), get_permalink( $children->post->ID ) ) . '</ul>'

Versioning scheme

I have adopted the same Ubuntu versioning scheme so the first release is 1107.

Other releases in the same month will be dot releases, eg the second release in July 2011 is 1107.1.

I love it, how can I show my appreciation?

If you have been impressed with this plugin and would like to somehow show some appreciation, rather than send a donation my way, please donate to your charity of choice. Feel free to leave a short note here if you’d like.

I will never ask for any form of reward or compensation. Helping others achieve their goals is satisfying enough 🙂

Questions or suggestions?

If you have questions or suggestions, please place them below.

1,136 thoughts on “Table of Contents Plus

    • Mike T says:

      It should be if you give it a relative width under Settings > TOC+. By default it is on auto so should scale appropriately and inherit any CSS specfications from your theme.

  1. hak76520 says:


    Thank you for your plugin.

    I’d like to editing the option, but it doesn’t work.
    I re-install TOC+, but the situation is the same as before and the option settings is still the same as before.

    How can I do that?
    Please help me.

    Best regards,

  2. Hi
    Love your plugin/widget. Works very well.
    But when I’m trying to get rid of the TOC in the page itself (want to have it in the right sidebar only) as soon as I click the box to “show the TOC in the sidebar only” within anpassen/widgets/TOC+ I get an error msg telling me that an error occurred (not further specified what one), and I must reload the page. Because of this I’m unable to set this for your widget. I’m using template twentythirteen.
    Any ideas?

    Tank you and kind regards

  3. Luke Skaff says:

    Please consider adding a parameter to be able to set an individual table of contents to the hide/collapse state initially, I know there is a global setting for this but would like to be able to do this on a per page basis. Thanks for making this plugin.

  4. Johannes says:

    Is it much effort to add an optional “Up” link right-aligned next to each linked heading to jump back to the TOC when you are somewhere down at the page?

  5. How can I enter show/hide info set at “Main Options” page into several languages? I can change text for these settings. But, once I change them, texts for all languages were changed. Can you make these options to one set per languages?

  6. Jorge says:

    When trying to use your plugin with betheme theme (or any other visual composer theme), it does only detect the content written in the wordpress editing form and nothing under the visual composer (which i use in all my pages…).

    Any solution to this ?


  7. Peter says:

    This is good stuff!!! Using polylang to handle multi-language site. I can handle the title using the LABEL attribute, but how to change show/hide info? Could you make it available to string translations in polylang?

  8. Hey,
    Just installed. Is there a away I can leave some space between the titles? right now each link in the TOC is right on top of each other.

    • Mike T says:

      The spacing is inherited from your theme but my guess you need to apply extra line height in your CSS, something like:

      .toc_list li {
      line-height: 2em;

  9. Hi,

    I already use the TOC Plugin for all my projects and I love it. For my new project I’d like to make it in a new look.

    Have a look at this screenshots:

    Is it possible to make the plugin stuck on the left or right sidebar? Also, is it possible then to show the anchors live during scrolling? So when I scroll further to “5. Beliebte Hersteller” it highlights the current anchor in the left content overview?

    I hope you understand my question 🙂
    Thanks in advance and
    Best Regards,

  10. Guy ROBERT says:

    Is it possible to generate a list of pages belonging to a given category, without having to exclude a cumbersome series of page ID’s ?

  11. Do you have a solution for creating collapsable headers? I’d like all the main heading content to have some way to collapse it from the sub-headings below them as I have a very lengthy TOC.

  12. Mabi says:

    Mike can I suggest you to show the most recent comments first?
    With nearly 1thousand, I had to click quite many times to see the latest here.
    thanks for the solid plugin, works perfectly.

  13. Mabi says:

    is it possible to have the sections of the toc expand and collapse all voices or one by one clicking on them?
    Also is it possible to set the TOC as sticky?

  14. Thanks, this is a really, really helpful plugin for my website, as each post is a book chapter and therefore very long ( Will put a donation into a charity box.

  15. Hi, thank you for the good plugin.
    I just realized the plugin is not compatible with some shortcode(‘title’ shortcode in avada).
    Is there any good way to use TOC+ with title shortcode?

    Thanks again.

  16. Jan Ilves says:


    I actually asked this question before, but never received a reply, maybe it`s because it was marked spam. Anyway, I have problems with the table of contents in mobile version, when I click the heading it simply does nothing, it does not even start loading. However, in desktop version everything looks good.

    I would add a website link, but I think then the comment would get flagged as spam or unapproved like last time.


    • Mike T says:

      It works OK for me on my mobile Safari on iPhone and iPad. I remember testing on (default and Dolphin) older Android 2.x devices back in the days.

      Which device and browser are you using?

  17. Hello,

    There is a bug with special characters ( ‘, <>, …) on anchor on version 1509.
    For example: l’intégrité is converted like this lrsquointegrite, so the special character ‘ is converted on rsquo.

    • Mike T says:

      Make sure you actually aren’t pasting in the HTML safe versions of your special characters. Switch over to the text (HTML) mode in your editor and look for words starting with & and ending with ;

      For example: &rsquo; is ’

  18. Hi Mike, I’m updating our web site and TOC plus looks like a good replacement for the toc we have now. I have a question:

    I’m intending to have the top horizontal menu bar ‘position:fixed’. This leads to the the section heading being obscured when the user clicks in the toc and the page moves. Is it possible to edit the code so that the page content is slightly lower and the heading can be seen? Maybe some padding? Help most appreciated!

    cheers, Heimir

    • Mike T says:

      Try enabling the smooth scroll option which caters to the WordPress admin bar but you can provide a different height adjustment in the advanced options.

    • Mike T says:

      By default, it shows the entire table of contents. If you didn’t change the default setting to closed then it is “remembering” that you had closed it last time. It uses cookies to remember if the user closed or opened it for next time. You can test it by using another browser at your site, or by clearing your cookies.

  19. Hello there. Thank you very much for this plugin. It seems to work very well, although I do have a problem: When pressing the headers in the TOC, it seems to move just a line or so beneath the header. Is there any way to change this, so that it moves to where the header itself is? I have testing it both being logged in and off as administrator, but the problem seems to persist.

    • Mike T says:

      Do you have a persistent bar across your site? Like a nav or admin bar? If you do, enable smooth scroll in the options. You can adjust the offset in the advanced section but the default caters to the admin bar.

  20. Thank you very much for this plugin. It seems to work very well, although I do have a problem: When pressing the headers in the TOC, it seems to move just a line or so beneath the header. Is there any way to change this, so that it moves to where the header itself is? I have testing it both being logged in and off as administrator, but the problem seems to persist.

  21. Pingback: Asset Importer fix for EPiServer Commerce 8 and CMS 8 -

  22. Pingback: Asset Importer for EPiServer Commerce 8 and CMS 8 -

  23. hello i got issue witch polish special chars:
    user test pass test

    there are letters missing. WordPress oryginally make alliases well.

    title was
    Czym są raki marmurkowe (Procambarus fallax) ?
    should be

    Czy to prawda, że pierwsze stadia młodociane są zabezpieczone liną asekuracyjną?

    Thanks for fix 🙂

    btw maybe it should work in posts text area as you see next h3 with related post is also included in table of contents 😀


    But hey, as long as you’re asking…. I have the plugin in a left-hand sidebar. Looks great. But as I scroll down, the TOC disappears.

    Is there any way to make the TOC slide down so it remains visible?

    I’ll send money and/or adult beverages, your choice.

  25. I’m looking for a way to build a TOC for a large site – say 200 pages. The site contains instructions on how do do certain tasks, and often one task is several pages long, or has sub-tasks. I see that you can use this as a sitemap page, but I want my TOC to sit in a sidebar. The idea is that a user can scroll up and down to find instructions for the task he’s interested in.

    Quite a few online SW help sites work this way, more or less, but so far the only way I can see to do it is my manually creating a 180-item menu, which is unwieldy to say the least, and not maintainable.

    Can this plugin help?

  26. conflict using Table of Content in combination with Rootstrap theme (2 posts)

    I encounter a conflict using Table of Content plugin in combination with Rootstrap theme.

    In my rootstrap-child theme I succesful deregister both rootstrap-bootstrap and rootstrap-icons to prevent loading bootstrap.min.css and font-awesome.min.css.

    After I activate the Table of Content plugin I notice that both css files are loaded again. Not in the header but in the footer instead. And the ID’s are rootstrap-bootstrap-css and rootstrap-icons-css.

    Is this something Table of Content is causing?

    • Mike T says:

      Although I haven’t used the Rootstrap theme, I can’t see why there would be a conflict between the two. TOC+ does not refer to Bootstrap or Font Awesome.

      Maybe other enqueued styles or scripts rely on the original Rootstrap things. That may explain why it would be loaded again to establish the minimum requirements.

  27. njs says:

    Heads up: WordPress 3.4 is giving the following error notice when this plugin is activated (and debug is on):

    Notice: The called constructor method for WP_Widget is deprecated since version 4.3.0! Use __construct() instead.

  28. Hi,
    I am Pole and would to latin characters won’t be cutted by regex, as it is in posts’ slug.
    Solution is simple – place `$return = remove_accents( $return );` before `$return = preg_replace( ‘/[^a-zA-Z0-9 \-_]*/’, ”, $return );` in toc.php
    However, it may make issues for previous users as they linked somewhere url with broken anchor (for example “Część pisemna” stripped to “cz_pisemna”).
    Maybe add it as option disabled by default?

  29. Pingback: Meine besten WordPress Plugins – Teil 3 Helfer im Blog | Designers-Inn

  30. Great Plugin! Works as a charm! 🙂

    Just a question about the sitemap shortcode. There are some pages in my project which I don’t want my users to see in the sitemap. I use those pages to test some future functionalities and they may or may not make it to the actual website some day.
    Is there a way to exclude some pages to appear in the sitemap?

  31. Pandoon says:


    Thank you for your plugin.

    About the anchor, it seems it doesn’t support the accent like é,è,à,… and it simply delete it, so is it possible to not delete the accent but remplace it by the equivalent like e,e,a, etc… ?
    And if there some special caracter like “, it doesn’t delete it but remplace by some caracters… so does it possible to ignore this caracters in the anchor?


  32. This really does the trick for me. Thank you!

    This is a bit ocd, but I went in under view source code and manually added a period after the numbered lists. Of course this doesn’t permanently change the actual file wherever this is.


    As it stands the TOC looks like

    1 Heading 1
    2 Heading 2
    3 Heading 3

    Can I go in the code and change to

    1. Heading 1
    2. Heading 2
    3. Heading 3

    I did find where I could change the weight and added a font-size to the toc_title and it worked so I’m not totally helpless! ;P

  33. Alex says:

    Hello. I’d like to know how I can place the TOC juste after the 1st heading (h1) and the introdution of my posts.

Comments are closed.