В последнее время я уже давно не встречал сайты, которые не имеют фиксированный header. Такой подход уже стал обычной практикой. Как минимум очень удобно когда навигация по сайту всегда находится под рукой. Но есть один момент, который может доставить дискомфорт при таком подходе — это якорные ссылки. Обычно при клике на такую ссылку, секция с указанным Id оказывается вверху окна браузера. И если header у нас имеет position: fixed, то ,следовательно, он будет перекрывать часть контента секции:

Есть много способов нивелировать данную проблему. В этой статье я предложу относительно универсальный способ. В нем мы будем также учитывать якорные ссылки, которые могут находится на разных страницах.
Готовый пример: https://codepen.io/jecosjmecos/pen/jORmQeg
Немного подробней остановимся на js коде:
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'
});
}
}
}
Здесь мы имеем функцию scrollToAnchor
. В качестве аргумента мы помещаем в нее id секции, которую нам необходимо будет показать в окне браузера. По умолчанию мы будем брать этот id из url текущей страницы (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'
});
}
}
В этой функции определяем высоту нашего header и проверяем наличие элемента с нужным id. Если такой присутствует, мы определяем координаты секции с учетом высоты header и плавно скролим к ней.
Вызывать функцию мы будем два раза. Один раз при загрузке страницы:
// 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);
}
});
});