Eine Scroll-Animation darf niemals den expliziten Wunsch nach weniger Bewegung übersteuern
scroll-behavior: smooth verwandelt Sprünge zu Anker-Zielen in eine animierte Bewegung, aber genau diese Animation kann bei Menschen mit vestibulären Störungen echte körperliche Beschwerden auslösen. Das robuste Pattern aktiviert smooth scrolling ausschließlich innerhalb von @media (prefers-reduced-motion: no-preference), sodass die explizite Entscheidung des Betriebssystems immer gewinnt.
Inhaltsverzeichnis
- 1. Was scroll-behavior: smooth genau bewirkt und wo es greift
- 2. Warum smooth scrolling für bewegungsempfindliche Nutzer ein echtes Problem ist
- 3. prefers-reduced-motion erkennen und als Schalter nutzen
- 4. Das robuste @media-Pattern: smooth nur bei no-preference aktivieren
- 5. Anker-Links und History-Navigation: wo scroll-behavior technisch greift
- 6. scrollIntoView() und scrollTo() aus JavaScript korrekt an das Pattern anschließen
- 7. Ausnahmen: wann eine kurze Animation trotzdem sinnvoll ist
- 8. Testen: Betriebssystem-Einstellung, DevTools-Emulation und manuelle Prüfung
- 9. Best Practices für ein barrierefreies Scroll-Verhalten
- 10. Zusammenfassung
- 11. FAQ
1. Was scroll-behavior: smooth genau bewirkt und wo es greift
Die CSS-Eigenschaft scroll-behavior: smooth sorgt dafür, dass ein Sprung zu einem Anker-Ziel, etwa über <a href="#abschnitt">, nicht abrupt, sondern als animierter Scrollvorgang über mehrere hundert Millisekunden abläuft. Gesetzt wird die Eigenschaft meist auf html, wodurch sie global für alle nativen Scroll-Auslöser innerhalb des Dokuments gilt, einschließlich Anker-Navigation, Tastatur-Scrolling mit Bild-auf/ab und programmatischem Scrollen über bestimmte JavaScript-APIs.
Der Effekt wirkt auf den ersten Blick rein kosmetisch, hat aber echte Auswirkungen auf die Orientierung: Ein animierter Scrollvorgang zeigt dem Nutzer visuell, wo auf der Seite er sich gerade befindet und wie weit das Ziel entfernt liegt, während ein abrupter Sprung diesen räumlichen Kontext komplett auslässt. Für die meisten Nutzer ist das ein angenehmes, orientierungsförderndes Detail, für eine bestimmte Nutzergruppe aber genau das Gegenteil.
2. Warum smooth scrolling für bewegungsempfindliche Nutzer ein echtes Problem ist
Menschen mit vestibulären Störungen oder allgemeiner Bewegungsempfindlichkeit können durch großflächige, schnelle Scroll-Animationen echte körperliche Symptome bekommen, von Schwindel bis Übelkeit, vor allem wenn die Animation groß, schnell und unerwartet ausgelöst wird. Ein einzelner Klick auf einen Inhaltsverzeichnis-Link, der die gesamte Seite in einer schnellen Bewegung durchscrollt, kann für diese Nutzergruppe ein reales Zugänglichkeitsproblem sein, nicht nur eine ästhetische Vorliebe.
Genau dafür existiert die Betriebssystem-Einstellung Bewegung reduzieren, die Nutzer bewusst aktivieren, um genau solche Animationen systemweit zu unterdrücken, und die Browser über die CSS Media Query prefers-reduced-motion: reduce zugänglich machen. Wer scroll-behavior: smooth ohne Rücksicht auf diese Einstellung global aktiviert, ignoriert eine explizit vom Nutzer getroffene Entscheidung und liefert genau die Erfahrung aus, vor der die Einstellung eigentlich schützen soll.
3. prefers-reduced-motion erkennen und als Schalter nutzen
Die Media Query prefers-reduced-motion kennt zwei Werte: no-preference, wenn der Nutzer keine besondere Einstellung getroffen hat, und reduce, wenn Bewegungsreduzierung im Betriebssystem aktiv ist. Wichtig ist die Reihenfolge der Logik: Statt smooth als Standard zu setzen und bei reduce wieder zu entfernen, ist die robustere Variante, standardmäßig beim Browser-Default auto zu bleiben und smooth ausschließlich innerhalb von @media (prefers-reduced-motion: no-preference) zu aktivieren.
Dieser Unterschied ist mehr als Geschmackssache: Browser ohne Unterstützung für die Media Query ignorieren die gesamte Regel und bleiben beim sicheren auto-Verhalten, während bei der umgekehrten Reihenfolge ein nicht unterstützender, aber trotzdem bewegungsempfindlicher Nutzer versehentlich smooth scrolling bekommen könnte, sobald ein anderer Browser-Fallback greift. no-preference als Aktivierungsbedingung zu verwenden ist damit die sicherere Grundhaltung.
/* Default: browser's native, instant scroll behavior */
html {
scroll-behavior: auto;
}
/* Only opt in to smooth scrolling when the user has not
requested reduced motion */
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}
4. Das robuste @media-Pattern: smooth nur bei no-preference aktivieren
Das robuste Grundmuster kombiniert die Media Query mit einer bewusst gewählten Standardeinstellung: scroll-behavior: auto ist der sichere Ausgangspunkt für html, weil er dem tatsächlichen Nutzerwunsch entspricht, solange keine explizite Präferenz für Animation vorliegt. Erst innerhalb von @media (prefers-reduced-motion: no-preference) wird smooth nachgerüstet, wodurch das Verhalten sich automatisch an jede Änderung der Betriebssystemeinstellung anpasst, ganz ohne JavaScript oder einen Seiten-Reload.
Für Projekte, die zusätzlich einen manuellen In-App-Schalter für Animationen anbieten wollen, lässt sich dasselbe Muster mit einem Datenattribut koppeln, das per JavaScript umgeschaltet wird, sobald der Nutzer die App-Einstellung ändert. Die Media Query bleibt dabei die primäre, automatische Quelle der Wahrheit, während der manuelle Schalter nur als zusätzliche, bewusste Übersteuerung für Nutzer dient, die eine andere Präferenz als ihr Betriebssystem haben.
html {
scroll-behavior: auto;
}
@media (prefers-reduced-motion: no-preference) {
/* data-motion="reduced" lets an in-app toggle override
the OS preference without touching JavaScript logic elsewhere */
html:not([data-motion="reduced"]) {
scroll-behavior: smooth;
}
}
html[data-motion="reduced"] {
scroll-behavior: auto;
}
5. Anker-Links und History-Navigation: wo scroll-behavior technisch greift
scroll-behavior: smooth wirkt technisch auf jeden Scrollvorgang, der als Ergebnis einer Navigation innerhalb desselben Dokuments ausgelöst wird: Klick auf einen Anker-Link mit Fragment-Identifier, Vor- und Zurück-Navigation im Browserverlauf, sofern das Ziel-Fragment sich ändert, sowie Tastatur-Navigation mit Bild-auf, Bild-ab, Pos1 und Ende, solange der fokussierte Kontext das Dokument selbst ist. Die Eigenschaft betrifft also nicht nur klickbare Links, sondern das gesamte native Scroll-Verhalten des Dokuments.
Nicht erfasst wird dagegen jedes Scrollen, das rein durch Mausrad, Trackpad-Geste oder Touch-Wischen ausgelöst wird, weil dieses Scrollen bereits kontinuierlich und nutzergesteuert erfolgt und keine diskrete Sprung-Animation braucht. Wer also Sorge hat, scroll-behavior: smooth würde normales Scrollen künstlich verlangsamen, kann beruhigt sein: Die Eigenschaft betrifft ausschließlich programmatisch oder per Navigation ausgelöste Sprünge zu einem bestimmten Ziel.
<nav>
<a href="#einleitung">Einleitung</a>
<a href="#hauptteil">Hauptteil</a>
<a href="#fazit">Fazit</a>
</nav>
<section id="einleitung">...</section>
<section id="hauptteil">...</section>
<section id="fazit">...</section>
<style>
/* These anchor jumps automatically become smooth once
scroll-behavior: smooth is active on <html> */
html {
scroll-behavior: auto;
}
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}
</style>
6. scrollIntoView() und scrollTo() aus JavaScript korrekt an das Pattern anschließen
Programmatisches Scrollen aus JavaScript über element.scrollIntoView() oder window.scrollTo() respektiert scroll-behavior: smooth auf html nur dann automatisch, wenn kein eigenes behavior-Argument übergeben wird oder wenn behavior: 'auto' explizit gesetzt ist. Wird dagegen im JavaScript-Aufruf hartkodiert behavior: 'smooth' übergeben, überschreibt dieser Aufruf jede CSS-Einstellung und ignoriert damit auch prefers-reduced-motion vollständig, was den ganzen CSS-basierten Schutzmechanismus aushebelt.
Die saubere Lösung ist, das Bewegungsverhalten an genau einer Stelle zu entscheiden, entweder ausschließlich über CSS und JavaScript-Aufrufe ohne explizites behavior, oder, falls JavaScript die Entscheidung treffen muss, die Media Query dort ebenfalls per window.matchMedia('(prefers-reduced-motion: reduce)') abzufragen und das Ergebnis konsistent in den behavior-Wert zu übersetzen, statt zwei parallele, widersprüchliche Quellen der Wahrheit zu pflegen.
const prefersReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
document
.querySelector("#zurueck-nach-oben")
.addEventListener("click", () => {
window.scrollTo({
top: 0,
behavior: prefersReducedMotion ? "auto" : "smooth",
});
});
7. Ausnahmen: wann eine kurze Animation trotzdem sinnvoll ist
Nicht jede Animation muss komplett verschwinden, sobald prefers-reduced-motion: reduce aktiv ist. Die Spezifikation und gängige Praxis unterscheiden zwischen großflächigen, räumlich weitreichenden Bewegungen, etwa das Durchscrollen einer kompletten langen Seite, und kleinen, kurzen Übergängen, etwa das sanfte Ein- und Ausblenden eines Tooltips über wenige Pixel und Millisekunden, die selbst für bewegungsempfindliche Nutzer meist unproblematisch bleiben.
Bei Scroll-Interaktionen empfiehlt sich deshalb eine differenzierte Betrachtung: Ein Sprung zu einem weit entfernten Abschnitt der Seite sollte bei reduzierter Bewegung tatsächlich sofort erfolgen, während ein sehr kurzer, wenige Pixel umfassender Korrektur-Scroll, etwa um ein Formularfeld knapp ins sichtbare Fenster zu rücken, in vielen Fällen auch mit aktivem reduce noch vertretbar ist. Im Zweifel gilt aber: lieber zu vorsichtig als zu sorglos mit der Nutzerpräferenz umgehen.
8. Testen: Betriebssystem-Einstellung, DevTools-Emulation und manuelle Prüfung
Die Einstellung Bewegung reduzieren findet sich unter Windows in den Bedienungshilfen, unter macOS in den Bedienungshilfen-Einstellungen unter Anzeige, und unter den meisten mobilen Betriebssystemen ebenfalls in den Bedienungshilfen-Menüs. Nach dem Aktivieren wertet jeder moderne Browser die CSS Media Query korrekt aus, ohne dass die Seite neu geladen werden muss, weil sich der berechnete Wert der Media Query live mit der Systemeinstellung ändert.
Für die Entwicklung bieten Chromium- und Firefox-DevTools eine Emulation von prefers-reduced-motion direkt im Rendering-Panel, mit der sich das Verhalten testen lässt, ohne die eigene Systemeinstellung dauerhaft zu ändern. Ergänzend lohnt sich ein kurzer manueller Test mit tatsächlich aktivierter Systemeinstellung, weil einzelne Browser-Engines bei der Emulation nicht jeden Edge Case exakt wie die echte Betriebssystem-Einstellung behandeln.
/* Quick visual debug helper: highlights every element whose
animation/transition is currently suppressed by the OS setting */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
}
9. Best Practices für ein barrierefreies Scroll-Verhalten
Ein barrierefreies Scroll-Verhalten braucht am Ende keine komplizierte Logik, sondern konsequente Reihenfolge: Standardmäßig auto, smooth ausschließlich innerhalb von @media (prefers-reduced-motion: no-preference), und jede JavaScript-Stelle, die selbst behavior setzt, an dieselbe Präferenzabfrage anschließen. So bleibt eine einzige, konsistente Quelle der Wahrheit für das gesamte Scroll-Verhalten der Seite erhalten.
Wer dieses Muster einmal global in html beziehungsweise in einer zentralen JavaScript-Utility etabliert, muss es für jede neue Komponente nicht erneut durchdenken, solange neue Scroll-Aufrufe konsequent ohne hartkodiertes behavior: 'smooth' auskommen. Das macht barrierefreies Scrollen zu einer einmaligen Architekturentscheidung statt zu einer wiederkehrenden Fehlerquelle bei jedem neuen Feature.
| Auslöser | Von scroll-behavior erfasst | prefers-reduced-motion beachten | Empfehlung |
|---|---|---|---|
| Anker-Link-Klick (#ziel) | Ja | Ja, automatisch über CSS | html { scroll-behavior: smooth } in Media Query |
| Browser-Vor/Zurück mit Fragment | Ja | Ja, automatisch über CSS | Kein Zusatzcode nötig |
| Mausrad, Trackpad, Touch-Wischen | Nein | Nicht relevant | Immer nutzergesteuert, keine Animation |
| scrollIntoView() ohne behavior | Ja, erbt CSS-Wert | Ja, automatisch über CSS | Kein explizites behavior übergeben |
| scrollTo({behavior:'smooth'}) hartkodiert | Nein, überschreibt CSS | Nein, muss manuell geprüft werden | matchMedia im JS selbst abfragen |
Mironsoft
Modernes CSS, Layout-Architektur und Rendering-Performance
CSS, das wartbar bleibt statt mit jeder Änderung zu brechen?
Wir prüfen bestehende Stylesheets auf Spezifitäts-Chaos und Layout-Thrashing und bauen daraus eine CSS-Architektur mit Cascade Layers, Custom Properties und modernen Layout-Primitiven, die auch nach dem zehnten Feature noch verständlich ist.
CSS-Audit
Spezifität, Cascade-Konflikte und ungenutzte Selektoren systematisch aufdecken.
Architektur-Refactoring
Cascade Layers, Custom Properties und Design Tokens sauber einführen.
Performance-Tuning
Layout-Thrashing, teure Selektoren und Rendering-Engpässe gezielt beheben.
10. Zusammenfassung
scroll-behavior: smooth und prefers-reduced-motion: Das Wichtigste auf einen Blick
Grundprinzip
scroll-behavior: smooth animiert Sprünge zu Ankern und programmatische Scrollziele, betrifft aber nicht Mausrad- oder Touch-Scrolling.
Sicheres Pattern
Standardmäßig auto, smooth nur innerhalb @media (prefers-reduced-motion: no-preference) aktivieren, niemals umgekehrt.
JavaScript-Falle
Hartkodiertes behavior: 'smooth' in scrollIntoView oder scrollTo überschreibt CSS und muss die Präferenz selbst über matchMedia abfragen.
Testen
DevTools-Emulation für schnelle Iteration, abschließend echte Systemeinstellung unter Windows, macOS und Mobilgeräten prüfen.