Tag Archives: wordpress

Auto add IDs and links to headings in WordPress

Seems simple, but I just want to add a small little working link icon like this next to each heading in my blog. I thought it was going to be a super easy thing, like install a plugin and be done. I thought wrong.

So this is multiple things in one. I want all headings to automatically get an HTML anchor, and I want each one to get a link icon that only shows up on hover to link to that HTML anchor.

Luckily Jeroen Sormani wrote a blog post that got me going in the right direction. But his blog fell short in a few places. It used older bootstrap icons, which no longer ship with WordPress. It also only worked with headings that you didn’t already specify an id on, existing headings that had an id wouldn’t get the fix. Finally, and this is more just a me thing, the hover showed up to the left of the heading, instead of to the right.

But all these things are easy fixes.

Get Font Awesome

First get yourself the Font Awesome WordPress plugin so you can get the link icon (and a bunch of other handy ones). It’s free, and only adds a few static resources to your pages from the official Font Awesome CDN, so your users likely already have it cached.

Add auto-id function

You will need to add a php function to your site theme to find all headings, and modify their output to include the HTML anchor as well as a clickable link icon. To do this in wp-admin, go to Appearance, then Theme Editor. Next you will select Theme Functions and add this to the php file.

/**
 * Automatically add IDs to headings such as <h2></h2>
 */
function auto_id_headings( $content ) {
    
    $content = preg_replace_callback( '/(\<h[1-6](.*?))\>(.*)(<\/h[1-6]>)/i', function( $matches ) {
        if ( ! stripos( $matches[0], 'id=' ) ) {
            $heading_link = '<a href="#' . sanitize_title( $matches[3] ) . '" class="heading-link"><i class="fas fa-link"></i></a>';
            $matches[0] = $matches[1] . $matches[2] . ' id="' . sanitize_title( $matches[3] ) . '">' . $matches[3] . $heading_link . $matches[4];
        } else {
            $startpos = stripos( $matches[2], 'id="') + 4;
            $endpos = stripos( $matches[2], '"', $startpos);
            $length = $endpos - $startpos;
            $title = substr( $matches[2], $startpos, $length);
            
            $heading_link = '<a href="#' . $title . '" class="heading-link"><i class="fas fa-link"></i></a>';
            $matches[0] = $matches[1] . '>' . $matches[3] . $heading_link . $matches[4];
        }
        
        return $matches[0];
        
    }, $content );
    
    return $content;
    
}
add_filter( 'the_content', 'auto_id_headings' );

The function above adds onto the original function by Jeroen. This one will also add the icon and link to headings which already had an ID as well.

Add CSS Styling

Finally we need to add some CSS styling to all this to get it to work and look proper. You may want to play with the margin settings here to your specific requirements. To add this, inside of wp-admin, go to Themes then Edit CSS. Add the following to your CSS styles.

/* hover links on headings */
h1 a.heading-link,h2 a.heading-link,h3 a.heading-link,h4 a.heading-link,h5 a.heading-link,h6 a.heading-link {
	opacity: 0;
	position: absolute;
	margin-left: 0.25rem;
}

h1:hover a.heading-link,h2:hover a.heading-link,h3:hover a.heading-link,h4:hover a.heading-link,h5:hover a.heading-link,h6:hover a.heading-link {
	opacity: 1
}

That’s it. Now all your existing and new headings will get auto-ids with little linkable icons next to them.