Scroll-Verhalten & Scroll Snap
Zuletzt aktualisiert am 15. Februar 2026
Mit CSS kannst du das Scroll-Verhalten deiner Website steuern: scroll-behavior macht Anker-Links sanft, scroll-snap sorgt dafür, dass Elemente wie in einem Karussell einrasten, und scroll-padding bzw. scroll-margin helfen dir, Offsets für Sticky Header einzubauen. Perfekt für moderne UIs mit Slidern und Fullscreen-Sections.
scroll-behavior: auto | smooth auto Grundlagen
scroll-behavior steuert, ob Scrollen abrupt oder sanft (smooth) erfolgt. Das gilt vor allem für programmatisches Scrollen (JavaScript scrollTo()) oder Anker-Links (<a href="#section">). Mit scroll-behavior: smooth auf dem html-Element wird jedes Scrollen animiert.
scroll-snap ist ein System aus mehreren Properties, das Elemente beim Scrollen magnetisch “einrasten” lässt. Du definierst auf dem Scroll-Container einen scroll-snap-type (z. B. x mandatory für horizontales Snapping) und auf den Kindern scroll-snap-align (z. B. start, center, end). So baust du Karussells, Fullscreen-Sections oder Slider ohne JavaScript.
scroll-padding und scroll-margin sind Offset-Werte, die beeinflussen, wohin gescrollt wird. scroll-padding fügt Innenabstand im Container hinzu (z. B. für Sticky Header), scroll-margin verschiebt den Snap-Point des Kindes. Beide werden in Pixeln oder relativen Einheiten angegeben.
Syntax & Werte
scroll-behavior
scroll-behavior wird auf dem scrollenden Element (meist html oder ein Container) gesetzt.
| Wert | Beschreibung | Beispiel |
|---|---|---|
auto | Sofortiges Scrollen (Standard-Verhalten des Browsers) | — |
smooth | Sanftes, animiertes Scrollen bei programmatischen oder Anker-Link-Aktionen | — |
scroll-snap-type
scroll-snap-type definiert die Snap-Achse und wie strikt gesnapped wird.
| Wert | Beschreibung | Beispiel |
|---|---|---|
none | Kein Scroll-Snapping (Standard) | — |
x mandatory | Horizontales Snapping, muss immer an einem Snap-Point enden | — |
x proximity | Horizontales Snapping, nur wenn nah genug an einem Snap-Point | — |
y mandatory | Vertikales Snapping, muss immer an einem Snap-Point enden | — |
y proximity | Vertikales Snapping, nur wenn nah genug | — |
both mandatory | Snapping in beide Richtungen (selten verwendet) | — |
scroll-snap-align
scroll-snap-align wird auf den Kind-Elementen gesetzt und bestimmt, an welchem Punkt sie einrasten.
| Wert | Beschreibung | Beispiel |
|---|---|---|
none | Dieses Element rastet nicht ein (Standard) | — |
start | Element rastet am Anfang des Containers ein (oben/links) | — |
center | Element rastet in der Mitte des Containers ein | — |
end | Element rastet am Ende des Containers ein (unten/rechts) | — |
scroll-padding & scroll-margin
Beide Properties nehmen Längen-Werte (wie padding und margin) und beeinflussen den Offset beim Scrollen.
| Wert | Beschreibung | Beispiel |
|---|---|---|
<length> | Feste Werte wie 20px, 2rem, 10vh etc. | — |
scroll-padding-top/right/bottom/left | Einzelne Seiten des Containers (wie padding) | — |
scroll-margin-top/right/bottom/left | Einzelne Seiten des Kind-Elements (wie margin) | — |
Beispiele
Smooth Scrolling: auto vs. smooth
Hier siehst du den Unterschied: Links springt der Container sofort zum Ziel (auto), rechts gleitet er sanft (smooth). Die Buttons steuern beide Container gleichzeitig per JavaScript.
/* Sofortiges Scrollen (Standard) */
.container-auto {
scroll-behavior: auto;
height: 300px;
overflow-y: auto;
}
/* Sanftes, animiertes Scrollen */
.container-smooth {
scroll-behavior: smooth;
height: 300px;
overflow-y: auto;
}
/* Oder auf html für die ganze Seite */
html {
scroll-behavior: smooth;
}<div class="demo-wrapper">
<div class="demo-buttons">
<button data-target="s1">Section 1</button>
<button data-target="s2">Section 2</button>
<button data-target="s3">Section 3</button>
</div>
<div class="demo-columns">
<div class="demo-col">
<div class="demo-label">scroll-behavior: auto</div>
<div class="scroll-auto">
<div id="auto-s1" class="section">Section 1</div>
<div id="auto-s2" class="section">Section 2</div>
<div id="auto-s3" class="section">Section 3</div>
</div>
</div>
<div class="demo-col">
<div class="demo-label">scroll-behavior: smooth</div>
<div class="scroll-smooth">
<div id="smooth-s1" class="section">Section 1</div>
<div id="smooth-s2" class="section">Section 2</div>
<div id="smooth-s3" class="section">Section 3</div>
</div>
</div>
</div>
</div>
<script>document.querySelectorAll('.demo-buttons button').forEach(function(btn){btn.addEventListener('click',function(){var id=this.getAttribute('data-target');var at=document.getElementById('auto-'+id);var st=document.getElementById('smooth-'+id);var ac=document.querySelector('.scroll-auto');var sc=document.querySelector('.scroll-smooth');if(at&&ac)ac.scrollTop=at.offsetTop;if(st&&sc)sc.scrollTop=st.offsetTop})});</script>Horizontales Bild-Karussell
Ein Karussell mit scroll-snap-type: x mandatory und scroll-snap-align: start auf den Items.
.carousel {
display: flex;
gap: 1rem;
overflow-x: auto;
scroll-snap-type: x mandatory; /* Horizontales Snapping */
padding: 1rem;
background: #f3f4f6;
border-radius: 8px;
}
.carousel-item {
min-width: 250px;
height: 150px;
background: linear-gradient(135deg, #1a56db, #7c3aed);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.5rem;
font-weight: 700;
scroll-snap-align: start; /* Rastet am linken Rand ein */
flex-shrink: 0;
}<div class="carousel">
<div class="carousel-item">Bild 1</div>
<div class="carousel-item">Bild 2</div>
<div class="carousel-item">Bild 3</div>
<div class="carousel-item">Bild 4</div>
<div class="carousel-item">Bild 5</div>
</div>Fullscreen-Sections (y mandatory)
Vertikale Fullscreen-Sections, die beim Scrollen einrasten. Perfekt für Landing-Pages.
.fullscreen-container {
height: 300px;
overflow-y: auto;
scroll-snap-type: y mandatory; /* Vertikales Snapping */
}
.fullscreen-section {
height: 100%; /* Jede Section ist Fullscreen */
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
font-weight: 700;
color: white;
scroll-snap-align: start; /* Rastet oben ein */
}
.section-1 {
background: linear-gradient(135deg, #1a56db, #0891b2);
}
.section-2 {
background: linear-gradient(135deg, #7c3aed, #dc2626);
}
.section-3 {
background: linear-gradient(135deg, #059669, #ea580c);
}<div class="fullscreen-container">
<div class="fullscreen-section section-1">Section 1</div>
<div class="fullscreen-section section-2">Section 2</div>
<div class="fullscreen-section section-3">Section 3</div>
</div>scroll-padding für Sticky Header
Wenn du einen Sticky Header hast, wird beim Scrollen zu einem Anker oft der Inhalt verdeckt. scroll-padding-top sorgt dafür, dass der Browser beim Scrollen zu Ankern oder per scrollIntoView() den Header-Offset automatisch berücksichtigt.
.sticky-demo {
scroll-behavior: smooth;
max-height: 300px;
overflow-y: auto;
scroll-padding-top: 60px; /* Offset für Sticky Header */
}
.sticky-header {
position: sticky;
top: 0;
background: #7c3aed;
color: white;
padding: 1rem;
font-weight: 700;
z-index: 10;
}
.sticky-section {
padding: 2rem 1rem;
border-bottom: 1px solid #ddd;
}<div class="sticky-demo">
<div class="sticky-header">
<a href="#part1">Part 1</a>
<a href="#part2">Part 2</a>
<a href="#part3">Part 3</a>
</div>
<section id="part1" class="sticky-section">
<h2>Part 1</h2>
<p>Ohne scroll-padding würde der Header diese Überschrift verdecken.</p>
<p>Dank scroll-padding-top: 60px bleibt der Abstand.</p>
</section>
<section id="part2" class="sticky-section">
<h2>Part 2</h2>
<p>scroll-padding-top kompensiert den Sticky Header automatisch.</p>
<p>Das funktioniert bei Anker-Links und scrollIntoView().</p>
</section>
<section id="part3" class="sticky-section">
<h2>Part 3</h2>
<p>Perfekt für Sticky Navs in Dokumentationen!</p>
</section>
</div>
<script>document.querySelectorAll('.sticky-header a').forEach(function(a){a.addEventListener('click',function(e){e.preventDefault();var t=document.querySelector(this.getAttribute('href'));var c=document.querySelector('.sticky-demo');if(t&&c)c.scrollTop=t.offsetTop-c.querySelector('.sticky-header').offsetHeight})});</script>Card-Slider mit proximity
Mit scroll-snap-type: x proximity rasten Karten nur ein, wenn der User nah genug scrollt. Das fühlt sich weniger “zwingend” an als mandatory.
.proximity-slider {
display: flex;
gap: 1rem;
overflow-x: auto;
scroll-snap-type: x proximity; /* Lockeres Snapping */
padding: 1rem;
background: #f3f4f6;
border-radius: 8px;
}
.proximity-card {
min-width: 200px;
height: 120px;
background: linear-gradient(135deg, #059669, #0891b2);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.25rem;
font-weight: 600;
scroll-snap-align: center; /* Rastet in der Mitte ein */
flex-shrink: 0;
}<div class="proximity-slider">
<div class="proximity-card">Card 1</div>
<div class="proximity-card">Card 2</div>
<div class="proximity-card">Card 3</div>
<div class="proximity-card">Card 4</div>
<div class="proximity-card">Card 5</div>
</div>Barrierefreiheit
scroll-behavior: smooth kann für Menschen mit Bewegungsempfindlichkeit problematisch sein. Nutze prefers-reduced-motion, um smooth scrolling zu deaktivieren:
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}scroll-snap-type: mandatory kann User “gefangen halten”, wenn sie versuchen, zwischen zwei Snap-Points zu scrollen. Teste ausgiebig auf Touch-Geräten und mit Tastatur-Navigation. proximity ist oft die bessere Wahl.
Stelle sicher, dass Tastatur-Navigation (Tab, Pfeiltasten) mit Scroll-Snap funktioniert. Browser scrollen automatisch zu fokussierten Elementen, aber scroll-padding hilft, dass Sticky Header den Fokus nicht verdecken.
Häufige Fehler
- scroll-behavior: smooth ohne prefers-reduced-motion: Kann bei Menschen mit Bewegungsempfindlichkeit Schwindel oder Übelkeit auslösen. Immer mit Media Query absichern.
- mandatory ohne genug Content: Wenn du
scroll-snap-type: x mandatoryhast, aber nur zwei Items in einem breiten Container, kann der User nicht “frei” scrollen. Teste mit verschiedenen Viewport-Größen. - scroll-padding vergessen bei Sticky Header: Ohne
scroll-padding-topverdeckt ein Sticky Header den Inhalt beim Scrollen zu Ankern. Setze den Wert auf die Header-Höhe. - scroll-snap-type auf Kindern statt Container:
scroll-snap-typegehört auf das scrollende Parent-Element,scroll-snap-alignauf die Kinder. Verwechsle das nicht. - Nicht auf Touch-Geräten testen: Scroll-Snap verhält sich auf Mobile oft anders als mit Maus oder Trackpad. Teste auf echten Geräten.
Browser-Kompatibilität
scroll-behavior wird seit 2018 in allen Browsern unterstützt. scroll-snap hat seit 2019 volle Unterstützung (CSS Scroll Snap Module Level 1).
| Client | Unterstützung | Hinweise |
|---|---|---|
| Chrome | Komplett | — |
| Firefox | Komplett | — |
| Safari | Komplett | — |
| Edge | Komplett | — |
| Opera | Komplett | — |
Email-Kompatibilität
Scroll-Verhalten funktioniert nicht in HTML-Emails. E-Mail-Clients blockieren scroll-behavior, scroll-snap und scrollbare Container.
| Client | Unterstützung | Hinweise |
|---|---|---|
| Apple Mail | Keine | Kein Support |
| Gmail | Keine | Kein Support |
| Outlook | Keine | Kein Support |
| Yahoo Mail | Keine | Kein Support |
| Thunderbird | Keine | Kein Support |
Verwandte Eigenschaften
Bleib auf dem Laufenden
Erhalte neue Inhalte direkt in dein Postfach
Was erwartet dich?
Neue Artikel & Videos
Wenn ich was Neues veröffentliche, erfährst du's hier zuerst.
Plattform & Kurs-Updates
Neue Kurse, Referenz-Updates und gelegentlich Sonderpreise zum Launch.
Einmal die Woche in deinem Postfach
Kurz, auf den Punkt, kein Spam.