Recently, I added fragment links to my Jekyll blog (see commits).
What this means is when you click on a heading element, the URL will update with the fragment id.
This is useful for bookmarking or sharing a page section. It can also be used when creating a table of contents.
Prerequisites
First, remove all existing heading links from your blog posts. You can find them by grepping the pattern:
git grep '# \[' -- _posts/
Or add the -l
option to get all the relative filepaths matching the pattern:
git grep -l '# \[' -- _posts/
Fragment links
Now add your fragment links. Append the script to the end of _layouts/post.html
:
<!-- _layouts/post.html -->
<script>
document
.querySelector('.post-content') // your selector for the post body
.querySelectorAll('h1,h2,h3,h4,h5,h6')
.forEach(function(heading) {
if (heading.id) {
heading.innerHTML =
'<a href="#' + heading.id + '">' + heading.innerText + '<\/a>';
}
});
</script>
The script does the following:
- looks for all post heading elements
- if the element has an
id
attribute, then the text will be surrounded with an anchor element linking to the fragment id
Example
If you have the following:
<h2 id="title">Title</h2>
Then it would be converted like so:
<h2 id="title">
<a href="#title">Title</a>
</h2>
Styling
To remove the anchor styles, you can inherit the heading styles:
// main.scss
.post-content {
h1,
h2,
h3,
h4,
h5,
h6 {
> a {
color: inherit;
}
}
}
If you want to display an icon when the element is active, focused, or hovered, then update your script with:
heading.innerHTML += '<span class="anchor-icon">§</span>';
Then add the CSS to toggle the icon display:
// main.scss
.post-content {
.anchor-icon {
display: none;
}
h1,
h2,
h3,
h4,
h5,
h6 {
> a {
&:active,
&:focus,
&:hover {
+ .anchor-icon {
display: inline-block;
}
}
}
}
}
And there you have it, heading links for your website!