Beweging

  • Gebruik clip-path en mask-image voor aangepaste geometrische onthullingen en vloeiende fade-outs.
  • Gebruik Scroll-Driven Animations (animation-timeline: scroll()) voor niet-essentiële scrollgebonden effecten in plaats van JS-listeners.
  • Gebruik Weergaveovergangen om naadloos te animeren tussen complexe indelingsstatussen.

Prestaties

  • Gebruik bij voorkeur animaties voor opacity en transform (waaronder afzonderlijke transformatie-eigenschappen, bijvoorbeeld translate in plaats van left/right/top/bottom) om te zorgen dat animaties in de samensteller-thread blijven.
  • Gebruik transition-behavior: allow-discrete, @starting-style en (voor elementen op de bovenste laag zoals <dialog> of [popover]) overlay om afzonderlijke begin- en eindstatussen native te animeren. Ga naar Het begin en einde van elementen animeren en Elementen animeren naar en van de bovenste laag.
.popover-reveal {
  /* Transition discrete display and top-layer overlay alongside opacity */
  transition:
    opacity ease-out,
    display,
    overlay;
  transition-duration: 0.2s;
  transition-behavior: allow-discrete;
}

Toegankelijkheid

Gebruik prefers-reduced-motion-mediaquery's om zware beweging uit te zetten voor gebruikers die dat liever hebben.

  • Zorg voor een pauzemechanisme: Sta gebruikers toe om automatisch uitgevoerde carrousels, banners of andere permanente animaties te stoppen.
  • Standaard statische weergaven: Overweeg om standaard statische statussen te gebruiken en gebruikers de mogelijkheid te geven zich aan te melden voor beweging.
  • Overschrijd de flitslimieten niet (3 per seconde): Gebruik nooit snel flitsen van licht naar donker. Deze effecten kunnen epileptische aanvallen veroorzaken.

Pas animation-duration: 0.01ms; NIET wereldwijd toe, omdat bepaalde animaties hierdoor meer schokkerig kunnen worden. In plaats daarvan kun je bewegingsvoorkeuren per geval afhandelen met een van de 2 benaderingen. Nest de query @media in de regel zodat beide versies bij elkaar blijven:

  • Begin met animaties die standaard aanstaan en maak ze minder opvallend met @media (prefers-reduced-motion: reduce):
/* Good: Dampen spin states or slow down animations for reduced motion */
.spinner {
  animation: spin 1s linear infinite;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
    opacity: 0.5;
  }
}

progress:not([value]) {
  animation: slide 1s infinite linear;
  @media (prefers-reduced-motion: reduce) {
    animation-duration: 20s;
  }
}
  • Begin standaard zonder animaties en zet ze aan met @media (prefers-reduced-motion: no-preference):
/* Good: Default to static or gentle states and opt-in to full motion */
.spinner {
  opacity: 0.5;
  @media (prefers-reduced-motion: no-preference) {
    opacity: 1;
    animation: spin 1s linear infinite;
  }
}

progress:not([value]) {
  animation: slide 20s infinite linear;
  @media (prefers-reduced-motion: no-preference) {
    animation-duration: 1s;
  }
}

Werken met animatie- en overgangsgebeurtenissen in JavaScript

In zowel de AnimationEvent-interface (animationstart, animationiteration, animationend, animationcancel) als de TransitionEvent-interface (transitionrun, transitionstart, transitionend, transitioncancel) geeft event.target je het oorspronkelijke DOM-element. Gebruik de alleen-lezen eigenschap event.animation om toegang te krijgen tot het specifieke Animation-object (Animation, CSSAnimation of CSSTransition) dat de gebeurtenis heeft geactiveerd.

Als event.animation niet beschikbaar is, kun je de Animation-instantie meestal vinden door event.target.getAnimations() aan te roepen en te filteren op event.animationName (of event.propertyName voor overgangen). We raden u aan event.animation rechtstreeks te gebruiken om verschillende scenario's te vermijden waarin deze reserveoptie die event.target.getAnimations() filtert, niet werkt zoals verwacht:

  • Animaties van de Web Animations API (element.animate()) hebben geen animationName, dus ze kunnen niet op naam worden gevonden als je filtert op event.target.getAnimations().
  • Filteren op animationName voor AnimationEvent's is dubbelzinnig als meerdere animaties met dezelfde naam aan hetzelfde element zijn gekoppeld.
    • Je kunt filteren op transitionProperty voor TransitionEvent's omdat er maar één gebeurtenis per overgangseigenschap is.
  • event.target verwijst altijd naar het oorspronkelijke DOM-element, dus er wordt geen onderscheid gemaakt tussen animaties die worden uitgevoerd op het element zelf en een van de pseudo-elementen, terwijl event.animation.effect.pseudoElement het doel-pseudo-element rechtstreeks blootstelt.
// Works in most basic CSS animation cases, but fails for WAAPI animations,
// duplicate animation names on the same element, or pseudo-elements.
document.addEventListener('animationstart', (event) => {
  const animation = event.target
    .getAnimations()
    .find((anim) => anim.animationName === event.animationName);
  console.log(animation);
});

// PREFERRED: Directly access the exact Animation object via event.animation
document.addEventListener('animationstart', (event) => {
  const animation = event.animation;
  console.log(animation);
});

Je kunt ondersteuning voor functieherkenning gebruiken met 'animation' in AnimationEvent.prototype (of 'animation' in TransitionEvent.prototype).