Communitygithub.com

igal-commits/animating-web-pages

Utilisez cette compétence pour ajouter ou corriger des animations sur une page web : révélations au défilement, intros héroïques, fondus enchaînés, boucles ambiantes, vidéo de fond en boucle, rotateurs d'images, éléments collants – ou lorsqu'une animation saccade, se déclenche au mauvais moment, joue hors écran ou ne s'exécute pas du tout.

Qu'est-ce que animating-web-pages ?

Cette compétence fournit un guide technique exhaustif pour diagnostiquer et résoudre les problèmes d'animation sur le web, couvrant à la fois les échecs d'exécution (animation qui ne se lance pas) et les problèmes de performance (saccades, déclenchements incorrects). Elle s'appuie sur un principe fondamental : avant d'ajuster les courbes d'accélération, il faut d'abord prouver que l'animation s'applique bien aux éléments ciblés. La compétence détaille les causes les plus fréquentes d'échec (sélecteurs CSS ne correspondant à aucun élément, états de repos manquants, déclencheurs évalués avant la fin du layout) avec des méthodes de vérification concrètes comme `document.querySelectorAll` ou l'inspection des propriétés calculées. Elle aborde également des cas spécifiques : animations au défilement (révélations, déclencheurs `ScrollTrigger`), vidéos en boucle (gestion du temps de lecture, redimensionnement selon l'appareil), éléments collants (`position: sticky` dans une grille CSS), et la gestion des boucles ambiantes ou des intros. Elle inclut des directives précises pour les animations ambiantes (intervalles lents et irréguliers, pause hors écran) ainsi que les mécanismes de repli pour l'accessibilité (mouvement réduit), l'absence de JavaScript, et les appareils mobiles. Une checklist de validation et des drapeaux rouges (comme `transition: all` ou l'ajout d'animations sans raison fonctionnelle) complètent le tout. Cette compétence est compatible avec tous les environnements où des animations CSS/JavaScript sont implémentées – sites vitrines, applications web, composants interactifs – et s'applique aussi bien aux bibliothèques d'animation (GSAP, ScrollTrigger) qu'aux transitions CSS natives.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/igal-commits/landing-page-skills/tree/HEAD/skills/animating-web-pages

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Animer des pages web

Aperçu

Les animations web échouent de deux manières : elles ne s'exécutent pas, ou elles s'exécutent mal. Chacune a des causes spécifiques et identifiables. Deviner les courbes d'accélération est la dernière chose à faire, pas la première.

Principe fondamental : avant de régler une animation, prouvez qu'elle s'applique bien aux éléments que vous ciblez.

Pour la conception de scènes épinglées et synchronisées au défilement, voir la compétence choreographing-scroll-stories. Celle-ci traite de la mécanique : faire en sorte que l'animation s'exécute et s'exécute correctement.

Quand une animation ne s'exécute pas du tout

Vérifiez dans cet ordre. Les trois premiers points expliquent la quasi-totalité des cas.

SymptômeCauseVérification
Rien ne bouge, éléments visiblesLe sélecteur ne correspond à aucun élémentdocument.querySelectorAll(sel).length dans la console
Rien ne bouge, éléments invisiblesLa divulgation a défini opacity: 0 et le déclencheur ne s'est jamais activéopacity calculée sur l'élément
Un fondu enchaîné ne se produit jamaisLes deux calques sont à opacity: 1 ; seule la règle "activé" existeIl doit exister une règle de repos définissant le calque entrant à 0
Se déclenche immédiatement au chargementLe déclencheur a été évalué avant la stabilisation du layoutExécuter après load, pas DOMContentLoaded, lorsque les images dimensionnent la page
Se déclenche une fois puis plus jamaisonce: true combiné à un élément qui rentre à nouveauEst-ce intentionnel ?
Rien ne s'exécute dans un onglet masqué ou un volet sans têteLe ticker est en pause quand document.hiddenForcer : gsap.ticker.lagSmoothing(0); gsap.ticker.tick()
Les déclencheurs sont décalés de quelques centaines de pixelsLes images ont été chargées après la mesure des déclencheursScrollTrigger.refresh() au chargement et au redimensionnement (debounce de 200 ms)

Le cas du fondu enchaîné mérite d'être détaillé car il semble correct lors d'une revue de code :

/* Ceci seul ne fait rien. */
.tile.is-swapped .layer.is-alt { opacity: 1 }

/* L'état de repos est ce qui en fait une animation. */
.layer.is-alt { opacity: 0 }
.tile.is-swapped .layer.is-alt { opacity: 1 }

Intros et animations ambiantes

  • Le titre doit être visible rapidement. Réduisez une intro pour que le titre apparaisse en environ 1,1 s. Une intro de 3,8 s est un écran de chargement.
  • Les photos changent par un fondu de sortie d'une cellule et un fondu d'entrée dans une autre. Elles ne glissent jamais. Chaque photo est un seul élément, jamais affiché deux fois à l'écran, et jamais en fondu de sortie pendant que sa copie entre en fondu.
  • Le changement ambiant est lent et irrégulier. Un carreau toutes les 1,8 à 3,4 s donne l'impression d'une grille vivante, tandis qu'un seul carreau change lentement. Ne réduisez pas l'intervalle pour accélérer le changement de chaque carreau.
  • Mélanger par rounds. Chaque carreau change une fois avant que le cycle ne se répète, et chaque sélection provient de la moitié la plus éloignée des trois derniers.
  • Mettre en pause ce que personne ne peut voir. Les boucles ambiantes s'arrêtent hors écran et dans un onglet masqué, et reprennent là où elles s'étaient arrêtées.
  • Les intros ne se rejouent pas à chaque retour. Une fois l'intro terminée, seule la couche ambiante bouge.

Révélations au défilement

  • Ne définissez opacity: 0 que sur les éléments qui sont réellement en dessous de la ligne de flottaison au chargement. Masquer systématiquement tout signifie que tout ce qui se trouve au-dessus est invisible jusqu'à un défilement qui n'aura peut-être jamais lieu.
  • Révélez à top 88%, pas à l'intersection complète. Attendre que l'élément soit totalement dans la vue signifie qu'il s'anime après que le lecteur le regarde déjà.
  • Échelonnez entre les frères, pas à l'intérieur d'un composant. 60-90 ms entre les cartes, 0 à l'intérieur d'une carte.
  • Regroupez avec un observateur par groupe plutôt qu'un par élément.

Vidéo

Une vidéo de fond en lecture automatique a un bogue universel : la vidéo joue hors écran, un observateur la met en pause, et au moment où le lecteur arrive, la boucle a 15 secondes de retard et le battement d'ouverture est perdu.

Supprimez complètement l'attribut autoplay.
appeler pause() et load() à l'initialisation.
À la première intersection uniquement : currentTime = 0, puis play().

Servez un fichier 1x en dessous de 992 px ou sous un ratio de pixels de 1,5, et une image de substitution pour le rendu avant le décodage de la vidéo. La vidéo lourde en page d'accueil consomme aussi de la bande passante : auditez-la.

Saccades

Un lent mouvement de dérive sur une photo fixe est la cause la plus fréquente. Un effet Ken Burns de moins d'environ 1 px par image rééchantillonne l'image à chaque image et donne l'impression de scintillement, pas de mouvement.

  • Soit bougez assez pour que ce soit un mouvement, soit ne bougez pas du tout.
  • Pour un arrêt dans une vidéo rendue, copiez l'image encodée octet par octet plutôt que de ré-encoder une image identique. Toute autre méthode dérive.
  • Vérifiez la jointure de la boucle. Si l'image 0 et la dernière image diffèrent, la boucle saute visiblement à chaque cycle. Mesurez la différence absolue moyenne entre elles.
  • Ne doublez pas le lissage. Une bibliothèque de défilement fluide associée à une valeur scrub élevée produit une page qui traîne derrière la molette. Si une bibliothèque de défilement fluide est présente, utilisez scrub: 0.2.

Éléments collants

position: sticky à l'intérieur d'une grille CSS se résout par rapport à la zone de la grille, pas au conteneur entier. Un élément collant qui n'est pas plus haut que son contenu n'a pas de déplacement et se libère immédiatement.

.grid  { align-items: stretch }      /* la zone fait maintenant toute la hauteur */
.col   { position: static; height: 100% }
.inner { position: sticky; top: 10rem }

Mécanismes de repli

Chaque animation bénéficie de trois mécanismes de repli, documentés dans le cahier des charges de l'animation et testés :

  • Mouvement réduit. prefers-reduced-motion: reduce et une requête ?static rendent les états empilés et finaux : rien d'épinglé, rien de masqué, chaque scène dans son état final. Couvrez également chaque transition CSS que vous avez ajoutée. Lister les sélecteurs animés mais oublier la transition sur le conteneur laisse une couleur qui se déplace toujours.
  • Pas de script. Tout reste visible. Une classe est ajoutée après environ 3,5 s si le script n'a jamais démarré, et le CSS révèle tout ce qui se trouve en dessous.
  • Téléphones. Les scènes épinglées s'empilent. Documentez-le, testez-le.

Vérification

Ne signalez pas une animation comme fonctionnant à partir du code. Confirmez dans la page :

  • Les compteurs de sélecteurs sont non nuls pour chaque groupe animé
  • La propriété calculée opacity sur un élément au-dessus de la ligne de flottaison est 1 avant tout défilement
  • La valeur currentTime de la vidéo est inférieure à 0,5 s au moment où elle devient visible pour la première fois
  • L'émulation de mouvement réduit laisse la page entièrement lisible et statique
  • L'absence de script laisse tout visible
  • Rien n'anime width, height, top ou left ; utilisez transform et opacity
  • Les boucles ambiantes n'effectuent aucun changement de style hors écran

Drapeaux rouges

  • Ajuster la durée ou l'accélération avant de confirmer que le sélecteur correspond
  • Une règle .is-active sans règle d'état de repos correspondante
  • transition: all
  • Une animation ajoutée parce que la section "semblait vide"
  • Une photo qui glisse
  • La même photo affichée deux fois à l'écran

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés