Hawk's By Design

I came across a very unique problem when I decided to give this site a little design update.

An example of the header anchor tag

I wanted to put anchor tags on the main headings, which are all h3s. I liked the look of it and the benefit of being able to target a specific section of the article. However, I soon realized that I would have to write in an anchor tag each time I wrote a heading.


To appease my laziness, I wrote a little bit of code to make it automatic.

Loop/Edit Headers

The code itself is really simple, right?

All we have to do is determine if we’re on an article page, and then grab all the h3s. After we have them, we inject an anchor tag that looks at the current header’s id attribute. Bing. Bam. Boom. We done.

Check For Article Page

var headers = document.querySelectorAll('#ArticleBody h3');
if(headers.length > 0) {
    // We have headers!
    // Do stuff

There were a couple of ways I could’ve used to determine if I was on an article page. A popular technique I’ve seen is to have WordPress add a bunch of class names to the html tag. Stuff like the template, or if there is a sidebar.

I don’t have that in my theme, pretty much because I don’t use it. Whenever I use a javascript selector, I like to either use the id or data attribute. I guess it’s separation of interests. I want my class names to relate to styling, so I try to not use them as selectors.

The solution was a pretty simple one. On my single article template I have the container of the article have an id. Easy.

Loop and Edit

for(var i = 0; i< headers.length; i++) {
    var id = headers[i].getAttribute('id');
    var text = headers[i].textContent;
    headers[i].innerHTML = '<a href="#' + id + '">#</a> ' + text;

As I said before, the loop is pretty simple. We have a selection of all of the h3s that are children of the id “ArticleBody”. We go through each header, store its id value, and then inject an anchor tag into its HTML with an href pointing to its id.

Just like that, we have automatic anchor tags for our headers!

A Little Extra

if(location.hash) {
    var el = document.querySelector(location.hash);
    if(el) {
        var offset = el.offsetTop;
        var a = el.querySelector('a');
        document.querySelector('#SiteContainer').scrollTop = offset;
        a.focus(); a.blur();

I had to add a little extra code due to the way I set up my pages. I like to have an all containing element on my pages instead of using the body tag (hence, “#SiteContainer”). One reason for this is the inconsistency with body tag styling on mobile. So, when a user navigates to the page with a hash, nothing happens because I’m scrolling this container instead of the body tag.

This code, like the previous, is still very simple. First a simple check to see if location.hash has a value, then if it is, we use that as a selector. Since the hash is an id, it works out. Just as an extra check, I make sure the selection actually returns something before continuing.

To scroll to the element, we have to know the distance to scroll, that’s where offsetTop comes into play. We get the offsetTop value of the selected element, then tell our container element that it’s scrollTop should reflect that value. The result is the container element scrolled right to our header.

For accessibility purposes, I also select the anchor tag within the header, give focus to it, then take that focus away. What this does is makes sure the tab sequence will start with the selected header instead of the top of the page. I used the anchor tag instead of the header because the anchor tag is natively tabbable.

Simple and Easy

This was a simple and easy way for me to keep my article writing simple. Sure, I could just write out an anchor tag each time I do a header, but where is the fun in that?! I mean, I do still have to give the header an id...

Thanks for reading!

Some more articles for you


January 24, 2019

Bracket Coloring: Pretty Colors Everywhere!

Have you ever struggled to find a matching bracket? Well I discovered an interesting little plugin that colorizes matching brackets.

View post


May 29, 2019

Intersection Observer: A Great New API

Finding out if an element is within the viewport has always been a pain in the butt. Luckily, there's a handy new API called Intersection Observer.

View post