Automatic Table of Contents for Long Posts
Builds a clickable table of contents from the H2 and H3 headings of long posts and places it above the content, adding anchor IDs to the headings.
Opens WPIDE on
Code
add_filter( 'the_content', function ( $content ) {
$min_headings = 3; // Show the table only with this many headings or more.
$post_types = array( 'post' );
$title = 'Contents';
if ( ! is_singular( $post_types ) || ! in_the_loop() || ! is_main_query() ) {
return $content;
}
if ( ! preg_match_all( '#<h([23])([^>]*)>(.*?)</h\1>#is', $content, $matches, PREG_SET_ORDER ) || count( $matches ) < $min_headings ) {
return $content;
}
$items = '';
$used = array();
foreach ( $matches as $match ) {
$text = wp_strip_all_tags( $match[3] );
if ( preg_match( '#\sid=["\']([^"\']+)["\']#', $match[2], $id_match ) ) {
$id = $id_match[1];
} else {
$id = sanitize_title( $text );
$id = $id ? $id : 'section';
$base = $id;
$n = 2;
while ( isset( $used[ $id ] ) ) {
$id = $base . '-' . $n++;
}
$content = preg_replace( '#' . preg_quote( $match[0], '#' ) . '#', '<h' . $match[1] . $match[2] . ' id="' . esc_attr( $id ) . '">' . $match[3] . '</h' . $match[1] . '>', $content, 1 );
}
$used[ $id ] = true;
$items .= sprintf( '<li class="wpide-toc-h%1$s"><a href="#%2$s">%3$s</a></li>', esc_attr( $match[1] ), esc_attr( $id ), esc_html( $text ) );
}
$toc = '<nav class="wpide-toc" aria-label="' . esc_attr( $title ) . '" style="margin:0 0 2em;padding:16px 20px;border:1px solid rgba(127,127,127,.3);border-radius:6px;">'
. '<p style="margin:0 0 .5em;font-weight:600;">' . esc_html( $title ) . '</p><ul style="margin:0;padding-left:1.2em;">' . $items . '</ul></nav>'
. '<style>.wpide-toc-h3{margin-left:1em;list-style:circle;}</style>';
return $toc . $content;
}, 20 );
Notes
Appears on posts with at least $min_headings headings. Change $post_types to use it on pages too.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.