{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "hide-on-scroll-header",
 "name": "Header verschwindet beim Runterscrollen, kehrt beim Hochscrollen zurück",
 "name_en": "Auto-hiding header (hide on scroll down, show on scroll up) / Smart sticky header (hide on scroll, scroll-state)",
 "kurz": "Beim Lesen gleitet der Header aus dem Bild, bei der ersten Bewegung nach oben ist er wieder da.",
 "kategorie": "Navigation",
 "kategorie_slug": "navigation",
 "kategorie_nr": 3,
 "bau_chat": "C3",
 "prioritaet": "A",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 2,
 "stimmung": [
  "ruhig",
  "präzise"
 ],
 "stimmung_roh": [
  "unaufdringlich",
  "funktional",
  "ruhig",
  "aufgeräumt"
 ],
 "technik": [
  "css",
  "scroll-state-queries",
  "vanilla-js",
  "scroll-driven-css"
 ],
 "technik_gruppen": [
  "css",
  "js"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "1) Am Seitenanfang steht der Header normal, oft durchsichtig über dem Hero. 2) Sobald die Seite sich bewegt, bekommt er eine Fläche, damit er auf jedem Untergrund lesbar bleibt. 3) Scrollt man nach unten, gleitet er um seine eigene Höhe nach oben aus dem Bild. 4) Bei jeder Bewegung nach oben kommt er sofort zurück. 5) Seit Chrome 144 geht das ohne Scroll-Listener in reinem CSS über scroll-state(scrolled).",
  "warum_es_wirkt": "Beim Lesen gehört der ganze Bildschirm dem Inhalt, die Navigation ist trotzdem nur einen Wisch entfernt. Das ist eine unsichtbare Qualität: Man bemerkt sie kaum, ihr Fehlen aber sofort. Der Wechsel der Fläche am Seitenanfang gibt dem Ganzen Feinschliff.",
  "wann_einsetzen": "Fast jede inhaltsreiche Seite mit fixem Header und langem Scroll: Fallstudien, Artikel, Journale, Produktseiten. Besonders wertvoll auf dem Telefon.",
  "wann_nicht": "Wenn der Header Aktionen trägt, die immer sichtbar sein müssen, etwa den Warenkorb im Checkout. Bei sehr kurzen Seiten. Wenn eine Smooth-Scroll-Bibliothek den nativen Scroll ersetzt, funktioniert die CSS-Lösung nicht, dann die JS-Variante mit deren Scroll-Ereignis nehmen.",
  "varianten": [
   "Ganz weg: der ganze Header gleitet hoch (diese Demo, Werte von Instrument)",
   "Logo bleibt: Fläche und Links gehen, die Marke bleibt als Pille stehen (diese Demo, Werte von COLLINS)",
   "Nur CSS: scroll-state(scrolled: bottom) ohne Scroll-Listener, Chrome 144+ (diese Demo)",
   "Sticky statt fixed: Header erst nach Scrollbeginn kleben lassen, Regeln in @container not scroll-state(scrolled: none)",
   "Mit Schrumpfen und Schatten über eine scroll()-Timeline",
   "Klebe-Zustand gestalten über @container scroll-state(stuck: top)",
   "JS mit Schwelle für Lenis oder ScrollSmoother über deren Scroll-Ereignis"
  ],
  "umsetzung": "Reines CSS (Chrome 144+): html { container-type: scroll-state } header { position: fixed; inset: 0 0 auto; transition: translate .2s ease-in-out } @container scroll-state(scrolled: bottom) { header { translate: 0 -100% } }. Die Fläche hängt an @container scroll-state(scrollable: top), also an „nicht ganz oben“. Ohne Unterstützung bleibt der Header einfach stehen, das ist ein guter Fallback.\n\nJS-Variante für alle Browser: Scroll-Listener passiv, pro Bild einmal per requestAnimationFrame prüfen. Weg seit dem letzten Bild aufsummieren, bei Richtungswechsel auf null setzen. Erst ab 8 px in einer Richtung die Klasse für „weg“ setzen, sonst zittert der Header. Bis zur eigenen Höhe vom Seitenanfang immer zeigen. Nur falls ein Eigenprojekt Lenis nutzt (optional, standardmäßig aus; viele Rezepte schließen es aus): lenis.on('scroll', ({ direction }) => …).\n\nFläche als eigene Ebene (::before) anlegen, dann blendet sie mit eigener Dauer und Verzögerung ein, unabhängig vom Gleiten. Gemessen: Instrument translate 200 ms ease-in-out, Fläche 350 ms; COLLINS translate 450 ms cubic-bezier(.215,.61,.355,1), Fläche 400 ms mit 200 ms Verzögerung.\n\nFallstricke: Header nie verstecken, solange etwas darin Fokus hat (header:focus-within { translate: none }). Für Ankersprünge scroll-padding-top in Headerhöhe setzen. scroll-state(scrolled) reagiert nur auf relative Scrolls (Rad, Wisch, Tasten, scrollBy), nicht auf scrollTo.",
  "mobil": "Hier lohnt es sich am meisten, weil wenig Höhe da ist. Mit der dynamischen Adressleiste testen, Höhen in svh oder dvh angeben, oben die Safe-Area (env(safe-area-inset-top)) einrechnen.",
  "reduzierte_bewegung": "Header dauerhaft sichtbar lassen und nur die Fläche wechseln, kurz überblendet. Alternativ die Transition entfernen, dann springt der Header.",
  "barrierefreiheit": "Solange Tastaturfokus im Header liegt, nie verstecken (:focus-within). Skip-Link anbieten. Kernaktionen nicht ausschließlich im versteckbaren Header anbieten."
 },
 "messwerte": {
  "easing": "ease-in-out (Instrument); cubic-bezier(.215,.61,.355,1) (Collins)",
  "dauer_ms": "200 (Instrument); 450 (Collins)",
  "stagger_ms": "",
  "distanz": "translateY 0 → -100 %",
  "sonstiges": "Hintergrund separat: .35s (Instrument), .4s mit .2s Verzögerung (Collins)",
  "herkunft": "beobachtet",
  "quelle": "https://www.instrument.com/",
  "aus_eintrag": [
   "hide-on-scroll-header"
  ]
 },
 "kurve": {
  "bezier": [
   0.42,
   0,
   0.58,
   1
  ],
  "css": "cubic-bezier(0.42, 0, 0.58, 1)",
  "name": "ease-in-out",
  "dauer_ms": 200
 },
 "gesehen_bei": [
  {
   "seite": "Una Kravets: Directional CSS with scroll-state(scrolled)",
   "url": "https://una.im/scroll-state-scrolled",
   "auszeichnung": "",
   "beobachtung": "Fixed- und Sticky-Variante, transition translate 0.2s, Rollout ab Chrome 144.",
   "art": "artikel"
  },
  {
   "seite": "modern-css.com: Auto-Hiding Header",
   "url": "https://modern-css.com/auto-hiding-header-without-scroll-listeners/",
   "auszeichnung": "",
   "beobachtung": "6 Zeilen CSS mit scroll-state(scrolled: block-end), transition .3s; kein Baseline, Fallback = Header bleibt sichtbar.",
   "art": "artikel"
  },
  {
   "seite": "Osmo: Scroll Driven Header Styling",
   "url": "https://osmo.supply/resource/scroll-driven-header-styling",
   "auszeichnung": "Osmo-Ressource",
   "beobachtung": "Nur Titel gesehen (Seite gesperrt).",
   "art": "demo"
  },
  {
   "seite": "Chrome Developers – scroll-state container queries (Chrome 133)",
   "url": "https://developer.chrome.com/blog/css-scroll-state-queries",
   "auszeichnung": "",
   "beobachtung": "container-type: scroll-state; @container scroll-state(stuck: top) { … } für Schatten am klebenden Nav.",
   "art": "artikel"
  },
  {
   "seite": "scroll-driven-animations.style – Shrinking Header + Shadow / Cover Card to Fixed Header",
   "url": "https://scroll-driven-animations.style/demos/shrinking-header-shadow/css/",
   "auszeichnung": "",
   "beobachtung": "Header-Schrumpfen und Schatten rein über scroll()-Timeline.",
   "art": "demo"
  },
  {
   "seite": "Instrument",
   "url": "https://www.instrument.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft (Inline-CSS): .global-header{position:sticky;top:0;transition:transform .2s ease-in-out,background-color .35s ease-in-out} .global-header--hide{transform:translateY(-100%)}, --sticky färbt den Hintergrund ein.",
   "art": "website"
  },
  {
   "seite": "COLLINS",
   "url": "https://www.wearecollins.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft (entry.DdWfn7dd.css): .app-header transition .45s transform var(--ease-out-cubic); .header--hidden translateY(-100%); .header--at-top blendet den Hintergrund aus (.4s, Verzögerung .2s); Klassen per Vue-Binding.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "Una Kravets: Directional CSS with scroll-state(scrolled)",
   "url": "https://una.im/scroll-state-scrolled"
  },
  {
   "titel": "modern-css.com: Auto-hiding header without scroll listeners",
   "url": "https://modern-css.com/auto-hiding-header-without-scroll-listeners/"
  },
  {
   "titel": "CSSWG: Scroll State Container Queries Explainer",
   "url": "https://drafts.csswg.org/css-conditional-5/scroll_state_explainer.md"
  },
  {
   "titel": "CSS scroll-state() queries",
   "url": "https://developer.chrome.com/blog/css-scroll-state-queries"
  },
  {
   "titel": "Shrinking Header + Shadow (CSS)",
   "url": "https://scroll-driven-animations.style/demos/shrinking-header-shadow/css/"
  },
  {
   "titel": "Cover Card to Fixed Header (CSS)",
   "url": "https://scroll-driven-animations.style/demos/cover-to-fixed-header/css/"
  }
 ],
 "kombinierbar_mit": [
  "sticky-shrink-header",
  "schwebende-pill-navigation",
  "mega-menue-morphing-viewport",
  "theme-farbwechsel-scroll",
  "scroll-fortschritt"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/navigation/hide-on-scroll-header/",
  "meta": "https://cecodesign.de/lab/fundus/navigation/hide-on-scroll-header/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/navigation/hide-on-scroll-header/demo"
 },
 "herkunft": {
  "quelldateien": [
   "navigation.json",
   "scroll.json",
   "patch-belege-3.json"
  ],
  "pruefnotizen": [
   "patch-belege-3.json: Zwei Produktionsbelege, beide klassenbasiert per JS.",
   "02.11.2026: lenis aus technik genommen; die Demo lädt Lenis nicht, Lenis ist nur optional (siehe bau.werte.lenis)."
  ],
  "zusammengelegt_aus": [
   "hide-on-scroll-header",
   "sticky-header-zustaende"
  ],
  "trendstatus_begruendung": "Konflikt etabliert (navigation) vs. aufsteigend (scroll). Aufgelöst zu 'etabliert': das Verhalten selbst ist Standard; aufsteigend ist nur die reine CSS-Umsetzung über scroll-state(), die als Variante geführt ist.",
  "querverweis_kategorien": [
   "Scroll & Section-Animationen"
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Beim Lesen gleitet der Header aus dem Bild, bei der ersten Bewegung nach oben ist er wieder da.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "distanz": "translateY 0 → -100 % (eigene Höhe), Header 76 px, unter 720 px Breite 64 px",
   "easing": "Ganz weg und Nur CSS: ease-in-out cubic-bezier(0.42, 0, 0.58, 1) · Logo bleibt: cubic-bezier(0.215, 0.61, 0.355, 1)",
   "dauer_ms": "Ganz weg und Nur CSS: 200 · Logo bleibt: 450",
   "hintergrund": "Fläche Papier 90 % (color-mix) mit blur(14px) saturate(1.2), Linie innen 1 px · Einblenden 350 ms ohne Verzögerung (Ganz weg) bzw. 400 ms mit 200 ms Verzögerung (Logo bleibt), gleiche Kurve wie das Gleiten",
   "schwelle_px": "8 px in einer Richtung, bevor der Header reagiert; bis zur eigenen Höhe vom Seitenanfang immer sichtbar",
   "logo_bleibt": "Fläche -100 %, Links und Knopf -120 % und Deckkraft 0, die Marke bekommt eine helle Pille mit Schatten 0 8px 28px",
   "css_variante": "html { container-type: scroll-state } · scroll-state(scrolled: bottom) → translate 0 -100% · scroll-state(scrollable: top) → Fläche an",
   "drosselung": "ein requestAnimationFrame pro Scroll-Bild, passiver Listener",
   "anker": "scroll-padding-top: Headerhöhe + 16 px",
   "lenis": "optional, standardmäßig aus: Demo lädt kein Lenis und läuft mit nativem Scroll (scroll-Ereignis bzw. CSS scroll-state). Lenis nur im Eigenprojekt; dann die JS-Variante mit lenis.on('scroll', ({ direction }) => …)."
  },
  "ausloeser": "scroll",
  "touch": "Gleiches Verhalten wie am Desktop, gesteuert über den Wisch. Links und Knopf werden unter 900 px zu einem Menü-Knopf; Safe-Area oben über env(safe-area-inset-top).",
  "reduziert": "Der Header bleibt immer stehen, nichts gleitet. Nur Fläche und Textfarbe wechseln beim Verlassen des Seitenanfangs, überblendet in 150 ms linear.",
  "korrekturen": {
   "beschreibung": "1) Am Seitenanfang steht der Header normal, oft durchsichtig über dem Hero. 2) Sobald die Seite sich bewegt, bekommt er eine Fläche, damit er auf jedem Untergrund lesbar bleibt. 3) Scrollt man nach unten, gleitet er um seine eigene Höhe nach oben aus dem Bild. 4) Bei jeder Bewegung nach oben kommt er sofort zurück. 5) Seit Chrome 144 geht das ohne Scroll-Listener in reinem CSS über scroll-state(scrolled).",
   "warum_es_wirkt": "Beim Lesen gehört der ganze Bildschirm dem Inhalt, die Navigation ist trotzdem nur einen Wisch entfernt. Das ist eine unsichtbare Qualität: Man bemerkt sie kaum, ihr Fehlen aber sofort. Der Wechsel der Fläche am Seitenanfang gibt dem Ganzen Feinschliff.",
   "wann_einsetzen": "Fast jede inhaltsreiche Seite mit fixem Header und langem Scroll: Fallstudien, Artikel, Journale, Produktseiten. Besonders wertvoll auf dem Telefon.",
   "wann_nicht": "Wenn der Header Aktionen trägt, die immer sichtbar sein müssen, etwa den Warenkorb im Checkout. Bei sehr kurzen Seiten. Wenn eine Smooth-Scroll-Bibliothek den nativen Scroll ersetzt, funktioniert die CSS-Lösung nicht, dann die JS-Variante mit deren Scroll-Ereignis nehmen.",
   "varianten": [
    "Ganz weg: der ganze Header gleitet hoch (diese Demo, Werte von Instrument)",
    "Logo bleibt: Fläche und Links gehen, die Marke bleibt als Pille stehen (diese Demo, Werte von COLLINS)",
    "Nur CSS: scroll-state(scrolled: bottom) ohne Scroll-Listener, Chrome 144+ (diese Demo)",
    "Sticky statt fixed: Header erst nach Scrollbeginn kleben lassen, Regeln in @container not scroll-state(scrolled: none)",
    "Mit Schrumpfen und Schatten über eine scroll()-Timeline",
    "Klebe-Zustand gestalten über @container scroll-state(stuck: top)",
    "JS mit Schwelle für Lenis oder ScrollSmoother über deren Scroll-Ereignis"
   ],
   "umsetzung": "Reines CSS (Chrome 144+): html { container-type: scroll-state } header { position: fixed; inset: 0 0 auto; transition: translate .2s ease-in-out } @container scroll-state(scrolled: bottom) { header { translate: 0 -100% } }. Die Fläche hängt an @container scroll-state(scrollable: top), also an „nicht ganz oben“. Ohne Unterstützung bleibt der Header einfach stehen, das ist ein guter Fallback.\n\nJS-Variante für alle Browser: Scroll-Listener passiv, pro Bild einmal per requestAnimationFrame prüfen. Weg seit dem letzten Bild aufsummieren, bei Richtungswechsel auf null setzen. Erst ab 8 px in einer Richtung die Klasse für „weg“ setzen, sonst zittert der Header. Bis zur eigenen Höhe vom Seitenanfang immer zeigen. Nur falls ein Eigenprojekt Lenis nutzt (optional, standardmäßig aus; viele Rezepte schließen es aus): lenis.on('scroll', ({ direction }) => …).\n\nFläche als eigene Ebene (::before) anlegen, dann blendet sie mit eigener Dauer und Verzögerung ein, unabhängig vom Gleiten. Gemessen: Instrument translate 200 ms ease-in-out, Fläche 350 ms; COLLINS translate 450 ms cubic-bezier(.215,.61,.355,1), Fläche 400 ms mit 200 ms Verzögerung.\n\nFallstricke: Header nie verstecken, solange etwas darin Fokus hat (header:focus-within { translate: none }). Für Ankersprünge scroll-padding-top in Headerhöhe setzen. scroll-state(scrolled) reagiert nur auf relative Scrolls (Rad, Wisch, Tasten, scrollBy), nicht auf scrollTo.",
   "mobil": "Hier lohnt es sich am meisten, weil wenig Höhe da ist. Mit der dynamischen Adressleiste testen, Höhen in svh oder dvh angeben, oben die Safe-Area (env(safe-area-inset-top)) einrechnen.",
   "reduzierte_bewegung": "Header dauerhaft sichtbar lassen und nur die Fläche wechseln, kurz überblendet. Alternativ die Transition entfernen, dann springt der Header.",
   "barrierefreiheit": "Solange Tastaturfokus im Header liegt, nie verstecken (:focus-within). Skip-Link anbieten. Kernaktionen nicht ausschließlich im versteckbaren Header anbieten."
  },
  "geprueft": "31.10.2026",
  "notiz": "Fallstudie eines erfundenen Markenbüros (Studio Wendel) für eine Buchhandlung mit Lesecafé. Der Header liegt durchsichtig über dem dunklen Hero und bekommt beim Scrollen eine Glasfläche. Umschalter für drei Varianten: Ganz weg (Instrument-Werte), Logo bleibt (COLLINS-Werte), Nur CSS (scroll-state, deaktiviert ohne Unterstützung). Die Anzeige unten liest den echten Zustand, in der CSS-Variante über eine Custom Property aus der Container-Query. Die Vorführung scrollt mit scrollBy, damit auch scroll-state(scrolled) die Richtung erkennt. Bilder 01.11.2026: eigene Bilder statt Portfolio. Zugang 02.11.2026: --leise .56 → .66 (5,5:1), Hex-Labels der Farbfelder opacity .7 → .9; Knopf-Rahmen im Kontrastmodus. Korrektur 02.11.2026 (KI-Audit Befund 2): bau.werte.lenis „optional, standardmäßig aus“; die Demo lud nie Lenis (nur technik im Katalog nennt es), umsetzung formuliert Lenis als Ausnahme."
 }
}
