The Best Way for Setting HTML Bookmark Scroll Offset

HTML bookmarks are a great tool, but sometimes they are a bit off and can cause confusion. You can fix it by setting an offset. Learn the best way for doing so.

HTML bookmarks are a great tool for making sure a visitor sees exactly the piece of information you intended him to see. But sometimes HTML bookmarks are a little bit off. Most commonly when sticky headers are involved, the bookmark (usually, a header) is covered by the header and can’t be seen. In these cases clarification is replaced by confusion – the user lands on what seems to be a random point on the page.

A couple of popular but not-so-good solutions

You can fix it by setting an offset, and there are a few methods for doing it. One involves dummy HTML elements, but I will skip it altogether because it is manual (had to be done for each bookmark), and it has an overhead if using a CMS, like WordPress. Another rather popular solution is:

/*** DON'T USE IT! ***/ [id] { margin-top: -40px; padding-top: 40px; }
Code language: CSS (css)

While it seems to be working at first sight, it can potentially cause problems in some cases. It will, for example, render elements overlapping with the above overlay not clickable.

:target pseudo-class to the rescue

Stack Overflow contains a better solution, but as it isn’t the first you might miss it:

/*** NOTE: A SLIGHTLY BETTER VERSION FOLLOWS BELOW ***/ :target::before { display: block; height: 180px; margin-top: -180px; content: ''; }
Code language: CSS (css)

Adjust the the px to your needs.

This solution uses the :target pseudo-class, which “represents a unique element (the target element) with an id matching the URL’s fragment” (MDN – Mozilla).

This works great in most cases, but I’ve found at least one case in which it doesn’t. The display: block; is crucial for the CSS to work. In most cases, bookmarks are made for heading elements, which displayed as blocks by default – hence no problem arises.

Making it even better – taking Scroll-To-Text Fragment into account

But there is another way for bookmarking: URL Scroll-To-Text Fragment – the #:~:text= URL part Google uses to conveniently highlight relevant text when you visit a search result. This feature (currently not supported on Firefox and Safari) nicely scrolls to and highlights a text snippet defined in the URL. The targets in this case (more loosely defined) aren’t necessarily displayed as blocks by default, and hence the above CSS can break their design. This is exactly what happened to me when bookmarking a summary text.

Luckily, the offset fix isn’t needed for Scroll-To-Text Fragment, as Chrome seems to scroll to position the fragment in the middle of the page, instead of the top of it. So, we need a way to differentiate between traditional HTML bookmarks and Scroll-To-Text Fragment. Traditional HTML bookmarks can only be used with id and name attributes (yes, name attribute as well, as I discovered recently). We can assume that if either an id or name attribute exists, a traditional HTML bookmark is being used, as it has better browser support. So, we can specify our CSS fix to only work in these cases:

/*** BEST VERSION I CAME UP WITH SO FAR ***/ [id]:target::before, [name]:target::before { display: block; height: 180px; margin-top: -180px; content: ''; }
Code language: CSS (css)

This isn’t bulletproof, but it’s close.

Conclusion

As sticky headers are pretty common, so is the problem of HTML bookmarks being a bit off. I’ve laid the popular solutions and highlighted and slightly improved the best one (to the best of my knowledge).

External links

Leave a comment

Your email address will not be published. Required fields are marked *