I have a page which makes use of the following:
- Headroom.js for a header which "slides out of view when scrolling down and slides back in when scrolling up"
- HTML
<a>
links to internal sections - Smooth scrolling
I want to ensure that, when the page scrolls to a particular anchor (be that due to clicking a link on the page to e.g. #bottom
, or manually adding the hash fragment to the URL, or following a redirect), the header doesn't get in the way of the anchor.
You can reproduce the problematic behaviour I'm talking about in the snippet below. Click the anchor to jump to the bottom of the page, and then click the link to jump back to the top.
Note that the header covers up the content which the browser has scrolled to.
How can I, in a robust manner, ensure that any scrolls due to navigating to an anchor element are offset by the height of the header (if visible) such that content appears in the right place?
One of the approaches I've experimented with involves unpinning the header as soon as a hashchange is detected, a la:
$(window).on('hashchange',function(){
setTimeout(() => {
headroom.unpin();
}, 0);
});
But for a smooth scroll, the hashchange event fires before the scrolling has finished. hence the header just gets repinned immediately. I also don't see any way to detect when the smooth scroll has finished.
Adding a click listener on the <a>
elements is not robust because it fails for users arriving at the page with a hash fragment already in the URL. It also fails for JavaScript changes to window.location.hash
. Similarly, listening on the hashchange event is also unreliable, because it doesn't fire if the user clicks an anchor, scrolls away and then clicks the same anchor again.
document.addEventListener("DOMContentLoaded", function(e) {
var headroom = new Headroom(document.querySelector(".header"), {
"offset": 205,
"tolerance": 5,
"classes": {
"initial": "animated",
"pinned": "slideDown",
"unpinned": "slideUp"
}
});
headroom.init();
});
html {
scroll-behavior: smooth;
}
.header {
position: fixed;
z-index: 10;
right: 0;
left: 0;
top: 0;
background-color: #292f36;
color: white;
text-align: center;
padding: 2rem 0;
}
p:nth-of-type(1) {
margin-top: 7rem;
}
body {
font-family: sans-serif;
}
.header {
animation-duration: 0.5s;
animation-fill-mode: both;
will-change: transform, opacity;
}
@keyframes slideDown {
0% {
transform: translateY(-100%)
}
100% {
transform: translateY(0)
}
}
.slideDown {
animation-name: slideDown;
}
@keyframes slideUp {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-100%);
}
}
.slideUp {
animation-name: slideUp;
}
<script src="https://npmcdn.com/headroom.js/dist/headroom.min.js"></script>
<div class="header">Here is my header</div>
<p id="top">Here is some text. Click to <a href="#bottom">jump</a> to the bottom of the page.</p>
<ul>
<li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li>
<li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
<li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
<li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
</ul>
<ul>
<li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li>
<li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
<li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
<li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
</ul>
<ul>
<li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li>
<li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
<li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
<li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
</ul>
<ul>
<li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li>
<li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
<li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
<li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
</ul>
<ul>
<li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li>
<li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
<li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
<li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
</ul>
<ul>
<li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li>
<li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li>
<li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li>
<li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li>
</ul>
<p id="bottom">Here is some more text. Click to <a href="#top">jump</a> to the top of the page.</p>