Recently, I haven’t seen any websites that have a static header for a long time. Almost all of them fix it at the top of the window. At least it’s very convenient to have the site navigation at your fingertips. But there is one thing that can cause discomfort with this approach: anchor links. Usually, when you click on such a link, the section with the specified Id appears at the top of the browser window. And if the header has a position: fixed, it means that it will overlap some of the content of the section:
There are many ways to mitigate this problem. In this article, I’m going to suggest a relatively universal way. In it, we will also take into account anchor links that may be located on different pages.
A ready-made example: https://codepen.io/jecosjmecos/pen/jORmQeg
Let’s take a closer look at the js code:
document.addEventListener('DOMContentLoaded', function() {
// Moving to anchor on page load
scrollToAnchor();
// Move to anchor when clicking on anchored links
const headerLinks = document.querySelectorAll('a[href*="#"]');
headerLinks.forEach(function(link) {
link.addEventListener('click', function(event) {
if(event.target.pathname === window.location.pathname){
event.preventDefault();
let hash = this.getAttribute('href').split('#')[1];
scrollToAnchor('#' + hash);
}
});
});
});
function scrollToAnchor(hash = window.location.hash) {
if(hash.length > 1){
let headerHeight = document.querySelector('header').offsetHeight,
targetElement = document.querySelector(hash);
if(targetElement) {
var targetOffset = targetElement.offsetTop - headerHeight;
window.scrollTo({
top: targetOffset,
behavior: 'smooth'
});
}
}
}
Here we have the scrollToAnchor
function. As an argument, we put in it the id of the section that we need to display in the browser window. By default, we will take this id from the url of the current page (window.location.hash
).
function scrollToAnchor(hash = window.location.hash) {
if(hash.length > 1){
let headerHeight = document.querySelector('header').offsetHeight,
targetElement = document.querySelector(hash);
if(targetElement) {
var targetOffset = targetElement.offsetTop - headerHeight;
window.scrollTo({
top: targetOffset,
behavior: 'smooth'
});
}
}
In this function, we determine the height of our header and check for an element with the required id. If there is one, we determine the coordinates of the section based on the height of the header and smoothly scroll to it.
We will call the function twice. Once when the page is loading:
// Moving to anchor on page load
scrollToAnchor();
The second time when you click on the link in the header menu:
// Move to anchor when clicking on anchored links
const headerLinks = document.querySelectorAll('a[href*="#"]');
headerLinks.forEach(function(link) {
link.addEventListener('click', function(event) {
if(event.target.pathname === window.location.pathname){
event.preventDefault();
let hash = this.getAttribute('href').split('#')[1];
scrollToAnchor('#' + hash);
}
});
});