fix: small header on scroll

This commit is contained in:
Tim Rijkse
2026-01-15 10:40:31 +01:00
parent 49d22484c0
commit 05c53baff7
4 changed files with 75 additions and 5 deletions

View File

@@ -1,15 +1,52 @@
/**
* Site Header Component
* Sticky header container that holds top-bar, navigation, and search
* Collapses on scroll down, expands on scroll up
* Based on: https://stackoverflow.com/questions/63902512/
*/
class SiteHeader extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.prevScrollPos = 0;
this.headerOffset = 0;
this.collapsibleHeight = 0;
this.handleScroll = this.handleScroll.bind(this);
}
connectedCallback() {
this.render();
this.collapsible = this.shadowRoot.querySelector(".collapsible");
window.addEventListener("scroll", this.handleScroll, { passive: true });
}
disconnectedCallback() {
window.removeEventListener("scroll", this.handleScroll);
}
handleScroll() {
const currentScrollPos = window.scrollY;
const isScrollingDown = currentScrollPos > this.prevScrollPos;
const delta = currentScrollPos - this.prevScrollPos;
if (!this.collapsibleHeight && this.collapsible) {
this.collapsibleHeight = this.collapsible.scrollHeight;
}
if (isScrollingDown) {
this.headerOffset = Math.min(
this.collapsibleHeight,
Math.max(0, this.headerOffset + delta)
);
this.classList.remove("reveal");
} else if (delta < 0) {
this.headerOffset = 0;
this.classList.add("reveal");
}
this.collapsible.style.transform = `translateY(-${this.headerOffset}px)`;
this.prevScrollPos = currentScrollPos;
}
render() {
@@ -20,17 +57,40 @@ class SiteHeader extends HTMLElement {
position: sticky;
top: 0;
z-index: 100;
background-color: var(--color-background, #ffffff);
background-color: transparent;
}
.header {
display: flex;
flex-direction: column;
overflow: hidden;
}
.collapsible {
position: relative;
z-index: 1;
overflow: hidden;
transform: translateY(0);
transition: none;
will-change: transform;
}
:host(.reveal) .collapsible {
transition: transform 220ms ease;
}
::slotted(top-bar) {
position: relative;
z-index: 2;
border-bottom: 1px solid var(--color-border, #e2e8f0);
}
</style>
<header class="header">
<slot></slot>
<slot name="top-bar"></slot>
<div class="collapsible">
<slot name="nav"></slot>
<slot name="search"></slot>
</div>
</header>
`;
}