WPSurfer.com

How to Create a Table of Content without a Plugin

Published on December 7, 2022 | Updated on April 12, 2024

I had been using a plugin to create a table of contents on all my posts automatically.

I knew that this could be done with a code snippet, so I used an AI tool to create the function necessary to add a table of content to all my posts.

The AI tool also helped me with the CSS to style the table of content.

I have used this code and it works as expected. Feel free to use it if you like the result.


Code to Create a Table of Content

Table of Content WordPress

This code is a WordPress filter function that adds a table of contents to your WordPress posts.

The function does this by looking for all headings in the content (<h2>, <h3>, etc.) and then creating a list of links that point to those headings.

The resulting table of contents is then inserted into the content before the first heading.

I usually add this function to my mu-plugin folder

<?php

/*
  Plugin Name: TOC
  Plugin URI: https://ticolibre.com
  Description: Add a Table of Content to all Posts Before the First Heading
  Version: 1.0
  Author: TicoLibre
  Author URI: https://ticolibre.com
*/


function add_table_of_contents_before_first_heading($content) {
  // check if the current post type is "post" and if the content contains at least one heading
  if(get_post_type() == 'post' && preg_match('/<h[2-6]/', $content)) {
    // Get language_picker custom field value
    $language_picker_value = get_post_meta(get_the_ID(), 'language_pick', true);

    // Set the table of contents title based on language_picker value
$toc_title = (strpos($language_picker_value, 'ES') !== false) ? '<p>Tabla de Contenidos</p>' : '<p>Table of Contents</p>';


    // generate the table of contents
    $table_of_contents = '<div class="table-of-contents">';
    $table_of_contents .= $toc_title;
    $table_of_contents .= '<ul>';
    

    // find all headings in the content
    preg_match_all('/<h([2-6])(.*?)>(.*?)<\/h[2-6]>/', $content, $matches);
    foreach($matches[0] as $key => $heading) {
      // extract the heading level and text
      $heading_level = $matches[1][$key];
      $heading_text = $matches[3][$key];

      // add the heading to the table of contents
      $table_of_contents .= '<li><a href="#'.sanitize_title($heading_text).'">'.$heading_text.'</a></li>';

      // add an anchor to the heading
      $content = str_replace($heading, '<a id="'.sanitize_title($heading_text).'"></a>'.$heading, $content);
    }

    $table_of_contents .= '</ul>';
    $table_of_contents .= '</div>';

    // Insert the table of contents before the first heading
    $content = preg_replace('/<h[2-6]/', $table_of_contents.'<h2', $content, 1);

    // Add a separator after the table of contents
    $content = preg_replace('/<\/div><h2/', '</div><hr class="wp-block-separator has-alpha-channel-opacity" style=""><h2', $content, 1);
  }

  return $content;
}
add_filter('the_content', 'add_table_of_contents_before_first_heading');

CSS to Style the Table of Content

You can add this CSS via the theme customizer to make sure that the table of content generated by the function looks like the table of contents generated by popular TOC plugins.

.table-of-contents {
    padding: 1em;
    background-color: #f8f8f8;
    border: 1px solid #ddd;
}
.table-of-contents h2 {
    margin-top: 0;
    margin-bottom: 0.5em;
}
.table-of-contents li {
    margin-bottom: 0.5em;
}
.table-of-contents a {
    color: #333;
    text-decoration: none;
}
.table-of-contents a:hover {
    text-decoration: underline;
}

In case you want to use the minified version of it, try this one:

/*TOC*/
.table-of-contents{padding:1em;background-color:#F7F9FF;border:1px solid #ddd;margin-bottom:25px}.table-of-contents p{font-weight:700;margin-top:0;margin-bottom:.5em}.table-of-contents li{margin-bottom:.3em}.table-of-contents a{color:#333;text-decoration:none}.table-of-contents a:hover{text-decoration:underline}

Once you like what you are seeing, you can keep the CSS in the theme customizer or you can inline in every page by style tags or you can add the CSS to your child them stylesheet.


Final Thoughts

A TOC allows users to quickly navigate to specific sections of a webpage or document, which can improve their overall experience.

As you can see creating and styling a table of content isn’t that complicated to implement.

Keep in mind that this custom plugin:

  • Doesn’t add any scripts which is one less thing to worry about if you care about site speed, but you won’t find a way to show and hide the TOC content like some TOC plugins do.

Manuel Campos

Manuel Campos

I am José Manuel. I am writing about things I know and things that I am learning about WordPress. I hope you find the content of this blog useful.