How to add an automatic offset to scroll position for hash-links

How to add an automatic offset to scroll position for hash-links

It's the subtle details that often make the most significant impact on user experience. One such detail that can frustrate users is when hash-links navigate to sections of a webpage, only to have those sections covered by a fixed navbar.

This issue arises because, by default, hash links scroll to positions that touch the browser window, disregarding fixed elements like navbars.

Imagine you're browsing a website with a fixed navbar, and a sidebar table of contents that offers easy navigation to different sections of a long-form article or a blog.

You click on one of the links in the table of contents, expecting to scroll to the corresponding section. Instead, you find yourself staring at the top of that section, hidden beneath the navbar.

The good news is that there's a simple solution to this problem, one that doesn't require diving into complex JavaScript code. Instead, a few lines of CSS can do the trick.

Understanding the issue

When a user clicks on a hash-link (e.g., #section2) within a page, the browser attempts to navigate to the corresponding element with the same ID (<div id="section2">).

However, if there are fixed headers, footers, or other elements that occupy space at the top of the viewport, the target element may end up hidden beneath them.

Solution: Use scroll-margin-top

As its name implies, this property bestows upon elements a top margin following a scroll event, effectively creating space between the top of the viewport and the targeted element.

h2 {
	scroll-margin-top: 50px; /* Adjust the value as needed */
}

/* For older versions of Safari (11 or older) */
@supports not (scroll-margin-top: 0) {
	h2 {
		scroll-snap-margin-top: 50px; /* Compatibility fallback */
	}
}

With this snippet, we ensure that when a user clicks on a hash-link, the browser gracefully scrolls to the designated section, leaving a comfortable buffer of 50 pixels between the section and the top of the viewport.

However, a word of caution: if you find yourself on Safari 11 or older (macOS or iOS), clicking anchor links may yield no response. Fear not. Incorporate the scroll-snap-margin-top property alongside scroll-margin-top.

Conclusion

While other methods may offer solutions dating back to the dawn of web development, the introduction of scroll-margin-top heralds a new era.


Joel Olawanle

Written by Joel Olawanle

Joel is a software engineer and teacher. He write's about software development, productivity, and life. He has written over 150 technical content that has helped millions of people all over the world.


Previous Post

A detailed Guide to data fetching in Next.js 14

Learn how Next.js 14 handles data fetching in server side components and client side components. This guide also covers the evolution of data fetching...

Next Post

How to add an automatic offset to scroll position for hash-links

Learn how Next.js 14 handles data fetching in server side components and client side components. This guide also covers the evolution of data fetching...