Sticky-Header einrichten
Ziel
Ein Seitenkopf, der beim Scrollen oben stehen bleibt, ohne Inhalt zu verdecken, auch nicht bei Sprunglinks auf Überschriften. Auf Wunsch mit Schatten, sobald er angedockt ist.
Voraussetzungen
- Keine. Alle Kernfunktionen sind laut
web-features3.38.0 Baseline widely available. - Für den Schatten im angedockten Zustand: Scroll-State-Queries, derzeit nur Chromium.
Getestet mit / Stand
Stand 2026-09-12. Am 2026-09-13 in Chrome 152 (macOS) getestet: Der Header klebt, der Schatten erscheint erst im angedockten Zustand, scroll-margin-top und die Alternative scroll-padding-top setzen das Sprungziel unter den Header, und beide Fallen (kurzer Wrapper, overflow am Vorfahren) lassen sich nachstellen. Nicht getestet: Firefox, Safari, Mobilgeräte. Wie sticky funktioniert, stammt von MDN, die Lösung für Sprunglinks von CSS-Tricks, der Schatten aus einem Chrome-Artikel.
Vorgehen
-
Header sticky machen, und zwar mit Schwellenwert. Ohne
top(oder eine andere Inset-Eigenschaft) verhält sichstickywierelative.1:root { --header-height: 4rem; } .site-header { position: sticky; top: 0; z-index: 10; min-block-size: var(--header-height); background: Canvas; }↗ Beispiel in neuem Tab öffnen
Der Hintergrund ist nötig, sonst scheint der Inhalt beim Scrollen durch.
-
Den Header als direktes Kind von
bodyplatzieren. Ein Element mitstickyklebt nur, bis es an den gegenüberliegenden Rand seines Containing Blocks stößt.1 Steckt der Header in einem Wrapper, der nur so hoch ist wie er selbst, bleibt ihm keine Strecke, auf der er kleben könnte. -
Kein
overflow: hidden | auto | scrollan Vorfahren. Das erzeugt einen „Scroll-Mechanismus“, an dem der Header dann klebt, auch wenn dieser Vorfahr gar nicht scrollt.1 -
Sprungziele unter dem Header sichtbar halten.2
:target, h2[id], h3[id] { scroll-margin-top: calc(var(--header-height) + 1rem); }↗ Beispiel in neuem Tab öffnen
Alternativ setzt man es einmal am Scroll-Container statt an jedem Ziel:
html { scroll-padding-top: calc(var(--header-height) + 1rem); } -
Optional: Schatten, sobald der Header angedockt ist. Abgefragt wird der Header selbst, reagieren kann aber nur ein Element darin.3
<header class="site-header"> <div class="site-header__inner">…</div> </header>@supports (container-type: scroll-state) { .site-header { container-type: scroll-state; } .site-header__inner { transition: box-shadow 0.3s ease; @container scroll-state(stuck: top) { box-shadow: 0 2px 8px rgb(0 0 0 / 15%); } } }
Warum funktioniert das?
flowchart LR A["Header im Fluss<br/>(wie relative)"] -- "Scrollen bis top: 0" --> B["angedockt<br/>(stuck)"] B -- "Ende des Containing Blocks<br/>erreicht" --> C["scrollt mit weg"] B -- "zurückscrollen" --> A
stickyist relativ positioniert, bis der Schwellenwert erreicht ist, und klebt dann bis zum Ende des Containing Blocks.1 Weil der Header bis dahin im normalen Fluss steht, braucht der Inhalt darunter anders als beiposition: fixedkeinpadding-topals Platzhalter. Das habe ich aus der Definition abgeleitet.- Ist
bodyder Containing Block, reicht die Strecke über die ganze Seite. Deshalb Schritt 2. scroll-margin-topvergrößert den Abstand, den der Browser beim Scrollen zu einem Ziel einhält. Ist er so groß wie der Header, landet die Überschrift sichtbar darunter.2- Mit
container-type: scroll-statelässt sich der Zustand „angedockt“, den der Browser selbst verwaltet, per Container Query abfragen.3
Fallstricke
sticky„funktioniert nicht“: Meist fehlttop, ein Vorfahr hatoverflowoder der Containing Block ist zu kurz.1z-index:stickyerzeugt immer einen eigenen Stacking Context.1 Positionierte Inhalte der Seite können trotzdem darüber liegen, wenn ihr Stacking Context höher liegt. Der Wert im Beispiel ist willkürlich.- Die Headerhöhe ändert sich (Umbruch auf kleinen Bildschirmen): Dann stimmt
--header-heightnicht mehr, und Sprungziele landen teilweise darunter. Die Variable bei den Breakpoints anpassen oder großzügig rechnen. - Ein hoher Header auf Mobilgeräten nimmt dauerhaft Platz weg. Das ist eine Frage der Gestaltung, keine technische.
- Ruckeln beim Scrollen: Inhalte mit
stickymüssen neu gezeichnet werden. MDN schlägtwill-change: transformvor.1 web.dev rät dagegen,will-changenur gezielt einzusetzen.4 Also erst messen, dann setzen. - Scroll-State-Queries gibt es nur in Chromium (ab 133). Ohne
@supportsist das kein Fehler, dann fehlt der Schatten einfach. Die Abfrage macht aber deutlich, was gemeint ist. - Header beim Herunterscrollen ausblenden und beim Hochscrollen zeigen: Das braucht bisher JavaScript, gehört nicht zu dieser Anleitung und ist nicht recherchiert.
- Bewegung: Wer den Header beim Andocken animiert (Größe, Position), packt das in
@media (prefers-reduced-motion: no-preference).3 Siehe Barrierearme Animationen.
Browsersupport
| Feature | Stand |
|---|---|
position: sticky | Baseline widely available (seit 2019-09-19 newly) |
scroll-margin-top, scroll-padding-top | Baseline widely available (seit 2021-04-26 newly) |
| Container Queries | Baseline widely available (seit 2023-02-14 newly) |
Scroll-State-Queries (stuck, snapped, scrollable) | limited: Chrome/Edge 133, Firefox und Safari fehlen |
Quelle: web-features 3.38.0 (Baseline-Daten der W3C WebDX Community Group), lokal abgefragt am 2026-09-12.
Siehe auch
- Hauptnavigation semantisch aufbauen
- Scroll-getriebene Animationen
- Mobile-Menü ohne Checkbox-Hack bauen
Quellen
- position CSS-Eigenschaft (MDN) — Definition von
sticky, Overflow-Falle, Stapelkontext, Performance - Fixed Headers and Jump Links – scroll-margin-top (CSS-Tricks) — Sprungziele unter festem Header
- CSS scroll-state() (Chrome for Developers) — Zustand „angedockt“ abfragen
- How to create high-performance CSS animations (web.dev) —
will-changegezielt einsetzen
Nicht aus den Quellen: scroll-padding-top als Alternative (Baseline-Daten und Chrome-Test), die Custom Property für die Headerhöhe, die Erklärung zum Wrapper in Schritt 2 (aus der MDN-Definition abgeleitet), das Diagramm und die Fallstricke zur wechselnden Headerhöhe.
Footnotes
-
position CSS-Eigenschaft (MDN), Abschnitte zu
stickyund „Accessibility“. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 -
Fixed Headers and Jump Links – scroll-margin-top (CSS-Tricks). ↩ ↩2
-
CSS scroll-state() (Chrome for Developers), Abschnitte „First scroll-state query“, „Progressive Enhancement“ und „Add a shadow when stuck“. ↩ ↩2 ↩3
-
How to create high-performance CSS animations (web.dev), Abschnitt „Force layer creation“. ↩