From 05c53baff721332576ba22d88d0f2c5d8bc20e88 Mon Sep 17 00:00:00 2001 From: Tim Rijkse Date: Thu, 15 Jan 2026 10:40:31 +0100 Subject: [PATCH] fix: small header on scroll --- css/styles.css | 9 ++++ index.html | 6 +-- js/components/horizontal-scroll-nav.js | 1 + js/components/site-header.js | 64 +++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/css/styles.css b/css/styles.css index 2da5b98..d57be8e 100644 --- a/css/styles.css +++ b/css/styles.css @@ -199,6 +199,9 @@ table { --color-push-box-bg: #EBEEF4; + /* Layout */ + --site-header-height: 210px; + --color-success: #22c55e; --color-error: #ef4444; --color-warning: #f59e0b; @@ -317,10 +320,16 @@ top-bar .actions { width: 100%; min-height: 100vh; margin: 0 auto; + padding-top: 0; background-color: var(--color-background); position: relative; } +site-content { + display: block; + padding-top: 16px; +} + @media (min-width: 431px) { body { display: flex; diff --git a/index.html b/index.html index 159b721..148e231 100644 --- a/index.html +++ b/index.html @@ -20,7 +20,7 @@
- +
- - + + diff --git a/js/components/horizontal-scroll-nav.js b/js/components/horizontal-scroll-nav.js index 4b0c2fd..2174481 100644 --- a/js/components/horizontal-scroll-nav.js +++ b/js/components/horizontal-scroll-nav.js @@ -66,6 +66,7 @@ class HorizontalScrollNav extends HTMLElement { scrollbar-width: none; -ms-overflow-style: none; padding: 0 16px; + background-color: #ffffff; } .nav-container::-webkit-scrollbar { diff --git a/js/components/site-header.js b/js/components/site-header.js index e32b45c..61931b5 100644 --- a/js/components/site-header.js +++ b/js/components/site-header.js @@ -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); }
- + +
+ + +
`; }