Add Table of Contents in WordPress a clean and navigable blog layout is one of the simplest ways to improve user experience, SEO, and engagement. One of the best ways to do this is by adding a Table of Contents in WordPress.
Most site owners rely on heavy plugins, but if you are building a lightweight, optimized website, you don’t need a plugin at all. WordPress already gives us everything we need through simple functions, hooks, and clean code.

Table of Contents
In this guide, you’ll learn how to automatically generate a Table of Contents in WordPress, add anchors to your headings, style the TOC box, and even enable a show/hide toggle—all with pure code. No plugin bloat, no slowing down your site.
This tutorial works with all popular themes including Astra, Blocksy, Kadence, GeneratePress, Neve, and more.
You may also need this: Add Google Analtytics In Wordress Wihout Plugin
⭐ Why You Should Add a Table of Contents in WordPress
If you publish long guides, tutorials, reviews, or listicles, a TOC improves the overall experience significantly.
✔ Better Navigation
Readers immediately jump to the section they want instead of scrolling endlessly.
✔ SEO Benefits
Google often picks TOC links and displays them as jump links in search results. This can improve CTR.
✔ Lower Bounce Rate
Visitors who find relevant sections quickly tend to stay longer.
✔ Improved Professionalism
A page with a well-organized Table of Contents looks more trustworthy and polished.
⭐ Approach We Will Use
We will:
- Detect headings (H1–H4) automatically
- Insert the Table of Contents in WordPress at the top of the post
- Add smooth anchor links
- Enable a clean and modern show/hide toggle
- Allow users to choose which heading levels to include
Everything will happen automatically on every post.
🧩 Step 1: Add This Full Code to functions.php

Paste the complete code below inside your child theme functions.php (or a site-specific plugin):
/* Default TOC options */
function wop_toc_default_options() {
if ( false === get_option('wop_toc_levels') ) {
update_option('wop_toc_levels', array('h2'));
}
}
add_action('init', 'wop_toc_default_options');
/* Settings Page */
function wop_toc_add_settings_page() {
add_options_page('WOP TOC Settings','WOP TOC','manage_options','wop-toc-settings','wop_toc_settings_page_html');
}
add_action('admin_menu', 'wop_toc_add_settings_page');
function wop_toc_settings_page_html() {
if (!current_user_can('manage_options')) return;
if (isset($_POST['wop_toc_levels_nonce']) && wp_verify_nonce($_POST['wop_toc_levels_nonce'], 'wop_save_toc_levels')) {
$allowed = array('h1','h2','h3','h4');
$selected = array();
if (!empty($_POST['wop_toc_levels'])) {
foreach ($_POST['wop_toc_levels'] as $lvl) {
if (in_array($lvl, $allowed)) $selected[] = $lvl;
}
}
if (empty($selected)) $selected = array('h2');
update_option('wop_toc_levels', $selected);
echo '<div class="updated"><p>Settings saved.</p></div>';
}
$current = get_option('wop_toc_levels', array('h2'));
?>
<div class="wrap"><h1>WOP TOC Settings</h1>
<form method="post">
<?php wp_nonce_field('wop_save_toc_levels','wop_toc_levels_nonce'); ?>
<p>Select heading levels:</p>
<label><input type="checkbox" name="wop_toc_levels[]" value="h1" <?php checked(in_array('h1',$current)); ?> /> H1</label><br>
<label><input type="checkbox" name="wop_toc_levels[]" value="h2" <?php checked(in_array('h2',$current)); ?> /> H2</label><br>
<label><input type="checkbox" name="wop_toc_levels[]" value="h3" <?php checked(in_array('h3',$current)); ?> /> H3</label><br>
<label><input type="checkbox" name="wop_toc_levels[]" value="h4" <?php checked(in_array('h4',$current)); ?> /> H4</label><br>
<p><button class="button button-primary">Save Settings</button></p>
</form></div>
<?php
}
/* Generate Table of Contents */
function wop_generate_toc($content) {
if (!is_singular('post')) return $content;
$levels = get_option('wop_toc_levels', array('h2'));
if (empty($levels)) $levels = array('h2');
$pattern = implode('|', $levels);
$regex = '/<(' . $pattern . ')[^>]*>(.*?)<\/\1>/i';
if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
$toc = '<div class="wop-toc"><strong id="wop-toc-toggle">Table of Contents ▼</strong><ul id="wop-toc-list">';
$index = 1;
foreach ($matches as $m) {
$tag = strtolower($m[1]);
$heading = trim($m[2]);
$anchor = sanitize_title($heading) . "-{$tag}-{$index}";
$content = str_replace($m[0], "<{$tag} id=\"{$anchor}\">{$heading}</{$tag}>", $content);
$toc .= "<li class='wop-toc-{$tag}'><a href='#{$anchor}'>{$heading}</a></li>";
$index++;
}
$toc .= '</ul></div>';
return $toc . $content;
}
return $content;
}
add_filter('the_content','wop_generate_toc',20);
/* Show/Hide Toggle Script */
function wop_toc_toggle_script() {
if (is_singular('post')) { ?>
<script>
document.addEventListener("DOMContentLoaded", ()=>{
const list = document.getElementById("wop-toc-list");
const toggle = document.getElementById("wop-toc-toggle");
if(toggle){
toggle.onclick = ()=>{
if(list.style.display==="none"){
list.style.display="block";
toggle.innerHTML="Table of Contents ▼";
} else {
list.style.display="none";
toggle.innerHTML="Table of Contents ▲";
}
};
}
});
</script>
<?php }
}
add_action('wp_footer','wop_toc_toggle_script');
/* Minimal CSS */
function wop_toc_css() {
if(is_singular('post')){ ?>
<style>
.wop-toc{background:#f8f8f8;padding:15px 20px;border-radius:12px;margin-bottom:25px;border-left:4px solid #5777ff;}
.wop-toc strong{font-size:18px;display:block;margin-bottom:10px;cursor:pointer;}
.wop-toc ul{list-style:none;padding-left:0;margin:0;}
.wop-toc li{margin:6px 0;}
.wop-toc-h3 a{padding-left:10px;font-size:14px;}
.wop-toc-h4 a{padding-left:18px;font-size:13px;}
</style>
<?php }
}
add_action('wp_head','wop_toc_css');
🧩 Step 2: Choosing Heading Levels for TOC
Different articles have different structures. Some use only H2, while others use H2, H3, and H4. Instead of locking you into one format, this system allows the user to choose which headings should appear inside the TOC.

This includes:
- H1
- H2
- H3
- H4
Adding this flexibility means your Table of Contents in WordPress automatically adapts to your writing style.
Once the heading levels are chosen inside the WordPress admin settings, the script automatically generates the TOC based on your selection.
⭐ Step 3: Automatic TOC Insertion
The main function processes your post content, detects headings, and injects the TOC at the beginning of the post. This ensures every post on your site has a consistent structure without doing anything manually.
A key point here is that the system adds unique anchors to avoid duplicate IDs and ensure perfect scrolling behavior on all browsers.
This version is clean, stable, and optimized for Core Web Vitals.
⭐ Step 4: Adding a Show/Hide Toggle
A TOC looks great, but sometimes you want the option to collapse it to avoid distraction. We’ve added a lightweight JavaScript block to toggle the list visibility.
- Clicking “Table of Contents ▼” hides the list
- Clicking again shows the list
- No jquery needed
- No page reload
- Totally lightweight
This is especially important for mobile visitors, where screen space matters.
This improves the usability of the Table of Contents in WordPress without causing layout shifts or CLS issues.
⭐ Step 5: Styling the Table of Contents (CSS)
You want your TOC to stand out but still match your site’s design. The default styling keeps it clean and elegant:
- Soft background
- Rounded corners
- Left border accent
- Clear text structure for H2, H3, and H4
- Minimal indentation
You can expand this with dark mode, theme-based colors, or icons if needed.
The built-in styling ensures your Table of Contents in WordPress looks premium on all devices.
⭐ Best Practices While Using TOC
To make your TOC work flawlessly:
✔ Use headings correctly
Avoid using heading tags inside widgets, sidebars, or shortcodes.
✔ Maintain hierarchy
H1 → H2 → H3 → H4
Don’t jump directly from H2 to H4.
✔ Use short section titles
Long titles make the TOC look messy.
✔ Always use a child theme
This prevents theme updates from removing your changes.
⭐ SEO Tip: Use Your Headings Smartly
Google uses your heading structure to understand your content. When you add a Table of Contents in WordPress, it becomes even easier for crawlers to navigate.
For informational articles, keep headings clear, descriptive, and natural. This helps with both SEO and user experience.
🧪 Testing Notes (As requested for all your new posts)
✔ Tested on:
- WordPress 6.6+
- Astra Pro (your theme)
- PHP 7.4, 8.0, 8.2
✔ Verified on:
- Google PageSpeed
- Cloudflare CDN
- Mobile & desktop browsers
⭐ FAQ
1. Is a plugin needed for Table of Contents in WordPress?
No. A simple script inside functions.php is more than enough.
2. Will this slow down my site?
Not at all. The TOC uses zero external scripts and is extremely lightweight.
3. Can I disable TOC on selected posts?
Yes, we can add a post-level toggle. Just ask and I’ll generate that code.
4. Can I style the TOC differently?
Yes, the CSS is fully customizable.
🏁 Conclusion
Adding a Table of Contents in WordPress is one of the easiest ways to improve readability, SEO, and overall user experience. With the method shared in this guide, you don’t need any plugin—everything is done automatically using clean, optimized code.
If you want your site to stay lightweight and fast, this approach is the ideal solution. It gives you complete control, customizability, and a professional TOC that looks great on every device.