MWCodebymw.de ↗
HTML & CSS

prefers-reduced-motion – Animationen, die niemandem übel werden

Manche Menschen bekommen von bewegten Oberflächen Schwindel oder Übelkeit. Ihr Betriebssystem weiß das längst – mit einer Media Query fragst du es einfach ab und lieferst dieselbe Seite ohne Bewegung aus.

Parallax, einfliegende Karten, sanft aufploppende Dialoge: Für die meisten sieht das gut aus. Für Menschen mit vestibulären Beschwerden ist es der Grund, eine Seite wieder zu schließen – bewegte Flächen können Schwindel und Übelkeit auslösen. Genau dafür gibt es in macOS, Windows, iOS und Android seit Jahren einen Schalter („Bewegung reduzieren"), und der Browser reicht ihn an dein CSS weiter.

Die eine Regel, die fast alles erledigt

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Warum 0.01ms statt none? Weil animationend und transitionend dann trotzdem feuern. Skripte, die auf das Ende einer Animation warten, laufen also weiter – sie warten nur nicht mehr.

Besser: bewusst gestalten statt pauschal abschalten

Die Holzhammer-Regel ist ein guter Sicherheitsgurt. Schöner wird es, wenn du je Effekt entscheidest. Ein Wechsel von Bewegung zu Überblendung bleibt oft verständlich, ohne zu stören:

.karte {
  transition: transform .3s ease, opacity .3s ease;
}

@media (prefers-reduced-motion: reduce) {
  .karte {
    transition: opacity .3s ease;   /* nur noch Helligkeit, keine Bewegung */
    transform: none;
  }
}

Umgekehrt geht es genauso: Animationen erst gar nicht anschalten, wenn niemand danach gefragt hat.

@media (prefers-reduced-motion: no-preference) {
  .hero { animation: schweben 6s ease-in-out infinite; }
}

Dasselbe in JavaScript

Wenn du mit requestAnimationFrame oder einer Bibliothek animierst, fragst du dieselbe Einstellung ab:

const ruhig = window.matchMedia('(prefers-reduced-motion: reduce)');
if (!ruhig.matches) starteAnimation();

// Reagiert auch, wenn jemand den Schalter im laufenden Betrieb umlegt
ruhig.addEventListener('change', e => e.matches ? stopAnimation() : starteAnimation());

Fallstrick

prefers-reduced-motion ist keine Erlaubnis, Bewegung ganz aus der Gestaltung zu streichen – und auch keine Ausrede, sie unbegrenzt einzusetzen, solange die Abfrage existiert. Zwei Dinge sind trotz Abfrage heikel: Bewegung, die automatisch startet und nicht anhält (Karussells, Videoschleifen), und alles, was über den halben Bildschirm wandert. Gib beidem einen Stopp-Knopf.

Ich baue Websites so, dass sie auf allen Geräten und für alle Besucher ruhig funktionieren. Wenn du das für dein Projekt brauchst: bymw.de.

Quellen

#CSS#Barrierefreiheit#Animation#Media Query#prefers-reduced-motion

Du brauchst mehr als ein Snippet?

Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.

Projekt anfragen →