Animation UX et performance en 2025 — Directives pratiques

Publié: 20 sept. 2025 · Temps de lecture: 5 min · Par la rédaction Unified Image Tools

Pourquoi l’animation en 2025

Les animations orientent l’attention et donnent du contexte. En 2025, elles doivent être rapides, accessibles et économes en énergie. Cette fiche vous aide à fixer un budget, choisir la bonne technique (CSS/WAAPI/Lottie/vidéo), et livrer sans régression.

Choisir le format

  • Boucles courtes/UI: WebP/AVIF animés
  • Réel/son: MP4/WebM (vidéo)
  • Transparence: WebP animé (vérifiez le support AVIF pour la transparence)

Note: évitez les GIF/APNG lourds; préférez MP4/WebM et sprites modernes.

Modèle d’implémentation

Exemple HTML de vidéo courte avec fallback image :

<video autoplay loop muted playsinline width="640" height="360" preload="metadata">
  <source src="/loop.webm" type="video/webm" />
  <source src="/loop.mp4" type="video/mp4" />
  {/* fallback */}
  <img src="/loop.jpg" alt="Boucle courte" />
  
</video>

Conseils d’expérience

  • Respectez prefers-reduced-motion et offrez une option d’arrêt.
  • Ne bloquez pas FCP/LCP: chargez tard et déclenchez proche de l’interaction.
  • Utilisez une vignette statique; chargez l’animation/vidéo au clic.

Accessibilité — réduire le mouvement

@media (prefers-reduced-motion: reduce) {
  .anim { animation: none !important; transition: none !important; }
}

Fournissez une alternative: fondu, changement d’opacité, ou coupure directe.

Couches de composition : déclenchez si nécessaire via will-change: transform, opacity. Préférez animer transform/opacity pour éviter le layout et contrôlez le nombre de couches afin d’épargner la mémoire GPU.

Budget d’animation

  • Durée: 120–240 ms pour micro-interactions; 300–500 ms pour transitions de page.
  • Distance: < 80 px pour les contenus essentiels; longues trajectoires seulement hors LCP.
  • Concurrence: pas plus de 2 animations simultanées dans le viewport critique.

Check-list

  • [ ] Migration GIF → WebP/AVIF/vidéo
  • [ ] Clarifier transparence et exigences de boucle
  • [ ] Respect de prefers-reduced-motion
  • [ ] Lazy‑load et cache optimisés

Études de cas

  • Indicateur de chargement: remplacé par CSS pur → −30 KB.
  • Héros animé converti en vidéo: GIF 2,4 MB → WebM 420 KB (qualité perçue équivalente).
  • Déclenchement au scroll: IntersectionObserver injecte src à 30 % de visibilité.

FAQ

  • Q: À quelle largeur arrêter la vidéo ?
    • R: Sur mobile, privilégiez preload="none", boucle courte et muette; laissez l’utilisateur déclencher l’extension.
  • Q: WebP ou AVIF ?
    • R: AVIF compresse mieux; conservez WebP en compatibilité.
  • Q: Impact SEO ?
    • R: Ne dégradez pas LCP/CLS. Évitez l’autoplay héro; utilisez une image poster statique et une lecture différée.
  • Q: Sous‑titres et accessibilité ?
    • R: Pour les vidéos porteuses de sens, fournissez des sous‑titres et supportez clavier/pause/lecture/réglage du volume.

Principes de conception — mouvement intentionnel

  • Sens: réserver le mouvement à l’explication d’un état, d’une hiérarchie ou d’une causalité.
  • Sécurité: éviter les clignotements >3 Hz et les zooms/rotations agressifs (WCAG 2.3.1).
  • Cohérence: un même composant garde tempo/éasing identiques.
  • Réversibilité: si l’animation échoue, l’UI statique doit rester pleinement fonctionnelle.

Durées et easings (repères concrets)

  • Micro-interactions: 120–180 ms, cubic-bezier(.2,0,0,1) ou ease-out court
  • Contenu/modales: 180–240 ms, ease-out
  • Transitions de page (cross-fade/slide): 240–320 ms, ease-in-out
  • Ressort (physique): amortissement 20–28, raideur 140–220 (repères)
.btn { transition: transform 160ms cubic-bezier(.2,0,0,1), box-shadow 160ms ease-out; }
.btn:active { transform: translateY(1px); }

Repères supplémentaires : cubic-bezier(0.2, 0, 0, 1) ; ressort : damping: 20–28, stiffness: 140–220.

Exemples WAAPI

const el = document.querySelector('.btn');
el?.animate([
  { transform: 'translateY(0)', opacity: 0.8 },
  { transform: 'translateY(-4px)', opacity: 1 }
], {
  duration: 160,
  easing: 'cubic-bezier(.2,.7,.2,1)',
  fill: 'both'
});
function springTo(el, to = 0, { stiffness = 180, damping = 22 } = {}) {
  let v = 0, x = 1; const dt = 1/60;
  function frame() {
    const f = -stiffness * (x - to) - damping * v;
    v += f * dt; x += v * dt;
    el.style.transform = `translateY(${x * 20}px)`;
    if (Math.abs(v) > 1e-3 || Math.abs(x - to) > 1e-3) requestAnimationFrame(frame);
  }
  frame();
}

Optimisations liées au scroll

  • Déclenchez l’animation quand l’élément devient visible (25–33%).
  • Minimisez le JS: utilisez position: sticky et évitez les calculs coûteux.
  • Privilégiez transform/opacity plutôt que top/left/width/height.

Lottie / CSS / Vidéo — arbitrage

  • Lottie (vecteur JSON): icônes UI et illustrations légères; couleurs remplaçables, indépendant de la résolution.
  • CSS: micro‑interactions; dépendances minimes, coût d’exécution bas.
  • Vidéo: rendu photo/complexe; excellente compression; sous‑titres/son possibles.

Critère: « qualité d’image prioritaire → Vidéo » / « boucle UI légère → CSS/Lottie » / « transparence requise → Lottie/WebP animé ».

Mesure et profilage

PerformanceObserver pour long tasks; DevTools pour layers et paint.

Mesurez CLS/INP et évitez les démarrages tardifs d’animation.

new PerformanceObserver((list) => {
  for (const e of list.getEntries()) console.log(e.entryType, e.name, e.duration);
}).observe({ entryTypes: ['longtask', 'measure'] });

performance.mark('anim:start');
// … démarrer l’animation …
performance.mark('anim:end');
performance.measure('anim:duration', 'anim:start', 'anim:end');
const io = new IntersectionObserver(es => es.forEach(e => e.isIntersecting && e.target.classList.add('in')), { threshold: 0.3 });
document.querySelectorAll('.reveal').forEach(n => io.observe(n));

Énergie et sécurité visuelle

  • Limitez surface/durée animée pour réduire la consommation et le jank.
  • Évitez le flicker 3–60 Hz; respectez WCAG 2.3.1.
  • Offrez pause/arrêt/masquage (WCAG 2.2.2).

Implémentation infaillible (sanity)

  • [ ] Objectifs/KPI définis (CTR/dwell/complétion)
  • [ ] Mouvement limité à transform/opacity (sans relayout)
  • [ ] Déclenchement par interaction ou visibilité (lazy)
  • [ ] Règles Reduced Motion et UI d’arrêt manuel
  • [ ] Test A/B si l’impact business est critique

FAQ étendue

  • Q: Lottie devient lourd ?
    • R: Réduisez primitives et framerate; sinon migrez vers vidéo.
  • Q: Et si je dois garder un GIF ?
    • R: Cas d’interop imposée uniquement; acceptez le compromis poids/qualité.
  • Q: Scroll jank ?
    • R: Combinez requestAnimationFrame + IntersectionObserver, évitez l’abus de will-change.

Articles liés