Scroll to element in hash after hero height is set

There's a bit of manually re-implementing what browsers already do here, but it's very simple and works very nicely
This commit is contained in:
Jake Howard 2022-07-20 22:57:50 +01:00
parent 38cc5182ca
commit 78b310faa3
Signed by: jake
GPG key ID: 57AFB45680EDD477

View file

@ -13,6 +13,12 @@ function setHeroHeight() {
ROOT.style.setProperty("--hero-height", `${getHeroHeight()}px`);
}
function scrollToElement(element, behavior = "smooth") {
const rect = element.getBoundingClientRect();
const top = rect.top - getHeroHeight();
window.scrollBy({ top: top, behavior });
}
function handleHeroStuck() {
if (HERO.getBoundingClientRect().top === 0) {
HERO.classList.add("stuck");
@ -39,11 +45,7 @@ window.addEventListener("load", () => {
document.querySelectorAll("#table-of-contents li a").forEach((element) => {
element.addEventListener("click", (event) => {
event.preventDefault();
const rect = document
.querySelector(event.target.hash)
.getBoundingClientRect();
const top = rect.top - getHeroHeight();
window.scrollBy({ top: top, behavior: "smooth" });
scrollToElement(document.querySelector(event.target.hash));
});
});
@ -56,7 +58,23 @@ window.addEventListener("load", () => {
});
});
window.addEventListener("DOMContentLoaded", () => {
setHeroHeight();
let scrollTarget = null;
try {
scrollTarget = document.getElementById(window.location.hash.slice(1));
} catch {
// Probably an invalid selector - just ignore it
}
if (!scrollTarget) {
return;
}
scrollToElement(scrollTarget, "auto");
});
window.addEventListener("resize", debounce(setHeroHeight, 2000));
window.addEventListener("load", setHeroHeight);
window.addEventListener("scroll", throttle(handleHeroStuck, 100));