- Utilisez
clip-pathetmask-imagepour des révélations géométriques personnalisées et des fondus enchaînés fluides. - Utilisez les animations basées sur le défilement (
animation-timeline: scroll()) pour les effets non essentiels liés au défilement au lieu des écouteurs JS. - Utilisez les transitions de vue pour animer facilement les transitions entre des états de mise en page complexes.
Performances
- Privilégiez l'animation de
opacityettransform(y compris les propriétés de transformation individuelles, par exempletranslateau lieu deleft/right/top/bottom) pour vous assurer que les animations restent sur le thread du compositeur. - Utilisez
transition-behavior: allow-discrete,@starting-styleet (pour les éléments de la couche supérieure comme<dialog>ou[popover])overlaypour animer de manière native les états d'entrée et de sortie discrets. Consultez Animer l'entrée et la sortie d'un élément et Animer des éléments vers et depuis la couche supérieure.
.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;
}
Accessibilité
Utilisez les requêtes média prefers-reduced-motion pour désactiver les mouvements importants pour les utilisateurs qui le souhaitent.
- Fournissez un mécanisme de mise en pause : permettez aux utilisateurs d'arrêter les carrousels, bannières ou autres animations persistantes qui s'exécutent automatiquement.
- Utilisez des vues statiques par défaut : envisagez d'utiliser des états statiques par défaut et de permettre aux utilisateurs d'activer le mouvement.
- Ne dépassez pas les limites de clignotement (trois par seconde) : n'incluez jamais de clignotement rapide de la lumière à l'obscurité. Ces effets peuvent provoquer des crises.
N'appliquez PAS animation-duration: 0.01ms; de manière globale, car cela peut rendre certaines animations plus saccadées.
Gérez plutôt les préférences de mouvement au cas par cas en utilisant l'une des deux approches suivantes, en imbriquant la requête @media dans la règle afin que les deux versions soient conservées ensemble :
- Commencez par activer les animations par défaut, puis atténuez-les à l'aide de
@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;
}
}
- Commencez par désactiver les animations par défaut, puis activez-les à l'aide de
@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;
}
}
Utiliser les événements d'animation et de transition en JavaScript
Sur les interfaces AnimationEvent (animationstart, animationiteration, animationend, animationcancel) et TransitionEvent (transitionrun, transitionstart, transitionend, transitioncancel), event.target vous donne l'élément DOM d'origine. Pour accéder à l'objet Animation spécifique (Animation, CSSAnimation ou CSSTransition) qui a déclenché l'événement, utilisez la propriété en lecture seule event.animation.
Lorsque event.animation n'est pas disponible, vous pouvez généralement trouver l'instance Animation en appelant event.target.getAnimations() et en filtrant par event.animationName (ou event.propertyName pour les transitions). Toutefois, il est préférable d'utiliser directement event.animation pour éviter plusieurs scénarios dans lesquels cette solution de remplacement qui filtre event.target.getAnimations() ne fonctionne pas comme prévu :
- Les animations de l'API Web Animations (
element.animate()) n'ont pas d'animationName. Elles ne peuvent donc pas être mises en correspondance par nom lors du filtrage deevent.target.getAnimations(). - Le filtrage par
animationNamepour lesAnimationEventest ambigu lorsque plusieurs animations portant le même nom sont associées au même élément.- Notez que le filtrage sur
transitionPropertypour lesTransitionEventfonctionne, car il n'y a qu'un seul événement par propriété de transition.
- Notez que le filtrage sur
event.targetpointe toujours vers l'élément DOM d'origine. Il ne fait donc pas de distinction entre les animations exécutées sur l'élément lui-même et celles exécutées sur l'un de ses pseudo-éléments, tandis queevent.animation.effect.pseudoElementexpose directement le pseudo-élément cible.
// 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);
});
Vous pouvez détecter la compatibilité à l'aide de 'animation' in AnimationEvent.prototype (ou 'animation' in TransitionEvent.prototype).