Communitygithub.com

apple-scroll-animation

Créez des animations de défilement à la Apple (scrollytelling) en HTML/CSS/JS pur, sans aucune bibliothèque. Idéal pour les pages où les éléments s'assemblent, s'illuminent, basculent, s'agrandissent ou changent au fil du défilement, comme les pages produit d'apple.com. Couvre les sections épinglées (sticky), le scrubbing basé sur la progression du défilement, les révélations mot par mot, les entrées d'éléments et les tests sans tête.

Qu'est-ce que apple-scroll-animation ?

Cette compétence permet de concevoir des animations de défilement sophistiquées, inspirées des pages produit d'Apple, en utilisant uniquement du HTML, CSS et JavaScript vanilla, sans aucune bibliothèque externe. Les effets sont contrôlés par la position de défilement et sont réversibles (le défilement vers l'arrière les lit en sens inverse). Elle repose sur trois concepts clés : l'épinglage (sticky) d'une section enfant à l'écran pendant que son conteneur défile, le calcul de la progression (un nombre entre 0 et 1) à partir de la position de défilement, et l'application directe des transformations CSS comme `translate`, `rotate`, `scale` et `opacité` à chaque image. La compétence inclut une liste d'effets prêts à l'emploi (assemblage, illumination de mots, stepper, inclinaison, cartes ascendantes, expansion) avec des formules précises, ainsi que des règles éprouvées pour éviter les bugs (séparation des propriétés CSS, gestion du `prefers-reduced-motion`, limites de distance de défilement, recomposition au redimensionnement). Elle fournit également une méthode complète pour tester les animations dans un navigateur Chrome sans tête via le protocole DevTools, avec capture d'écran à différentes étapes. Cette compétence cible les développeurs front-end souhaitant créer des expériences de scrollytelling fluides et professionnelles sans dépendre de frameworks ou bibliothèques tierces.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MananShukla007/apple-scroll-animation/tree/HEAD/skills/apple-scroll-animation

Demander à votre IA préférée

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

Documentation

Animation de défilement style Apple

Les effets sont contrôlés par la position de défilement, pas par un minuteur. Le défilement vers le haut les lit en sens inverse. Aucune bibliothèque nécessaire.

Les trois idées

  1. Épingler. Un conteneur haut (par ex. height: 300vh) contient un enfant position: sticky; top: 0; height: 100vh; overflow: hidden. L'enfant reste à l'écran pendant que le conteneur défile. La hauteur supplémentaire du conteneur constitue votre budget d'animation.
  2. Progression. Une fonction transforme la position de défilement en un nombre 0..1 :
    • section épinglée : clamp(-rect.top / (rect.height - innerHeight))
    • élément entrant dans la fenêtre : clamp((innerHeight*a - rect.top) / (innerHeight*(a-b)))
  3. Pilotez les visuels à partir du nombre. Définissez translate, rotate, scale, opacity (et borderRadius) à chaque image. Un seul écouteur scroll régulé avec requestAnimationFrame recalcule tout.

Moteur prêt à coller : references/scroll-engine.js.

Effets qui fonctionnent bien (choisissez-en 3 à 5, pas tous)

EffetComment faire
AssemblageLes éléments commencent dispersés autour des bords de la fenêtre (angle aléatoire, rotation, échelle .35, opacité .2) et rejoignent leur position finale. Calculez le décalage de chaque élément par rapport à sa place naturelle une fois (au chargement/redimensionnement), puis multipliez par (1 - ease(p)). Décalez par index.
Illumination de motsEnveloppez chaque mot dans une balise span. Opacité .18 → 1 avec clamp(p * 1.25 * N - k).
Stepper épingléstep = floor(p * N) ; la fraction p*N - step remplit une barre de progression à l'intérieur de l'étape active. Cliquer sur une étape doit faire scrollTo vers sa position.
Inclinaisonperspective(1400px) rotateX((1-e)*22deg) translateY((1-e)*60px) scale(.84 + .16*e) pour une maquette de téléphone/appareil.
Cartes ascendantestranslate: 0 (1-e)*80px; scale: .9+.1e; opacity: e, retard par colonne (i % cols).
ExpansionVidéo/image scale .78 → 1 et borderRadius 44px → 28px.

Utilisez ease = t => 1 - (1-t)**3 sur la progression avant de l'appliquer.

Règles (apprises à la dure)

  • Utilisez les propriétés CSS individuelles translate, rotate, scale pour le scrubbing, et gardez transform pour le survol. Sinon, le survol et le défilement se disputent la même propriété.
  • Ne combinez pas une classe .reveal de fondu avec une transformation scrubbée sur le même élément. Choisissez-en une seule.
  • Placez le titre de la section à l'intérieur du panneau épinglé avec le contenu. Si le panneau ne contient que le contenu centré, les écrans hauts affichent une grande zone vide.
  • Gardez la distance de défilement modeste. Environ N * 55vh + 100vh pour un stepper à N étapes, 240-300vh pour un effet unique. Les utilisateurs trouvent 700vh+ fatigant.
  • Limitez ce qui est épinglé à ce qui tient dans 100vh. Sur les écrans courts (max-height: 820px) et les téléphones, masquez les sous-titres et les extras, et n'affichez que l'étape active dans un stepper.
  • Mouvement réduit : si prefers-reduced-motion: reduce, renvoyez une progression 1 partout (état final, pas de mouvement). Ne laissez pas les éléments cachés.
  • Sticky ne nécessite pas overflow sur les ancêtres sauf overflow-x: hidden sur body, ce qui est acceptable. Évitez overflow: hidden sur tout conteneur entre l'élément sticky et la page.
  • Recalculez lors du redimensionnement (les décalages d'assemblage dépendent de la mise en page).
  • Animez uniquement translate/rotate/scale/opacity/border-radius ; évitez les propriétés de mise en page.
  • Évitez un premier/dernier segment de vidéo minuscule : si vous scrubbiez la lecture <video>, les courts extraits peuvent s'afficher vides.

Ordre typique de la page

Hero (épinglé, assemblage) → une déclaration simple (sans effet) → preuve/film (expansion) → stepper épinglé → maquette d'appareil (inclinaison) → grille de cartes (ascension) → CTA. Alternez les sections noires et gris clair pour l'ambiance Apple ; une couleur d'accent.

Test

Le --screenshot de Chrome sans tête ne peut pas défiler. Pilotez un vrai Chrome via le protocole DevTools à la place :

  1. chrome --headless=new --remote-debugging-port=9333 --user-data-dir=/tmp/prof about:blank &
  2. Depuis Node (v22+ a WebSocket global) : fetch http://localhost:9333/json, ouvrez le webSocketDebuggerUrl de la page, envoyez Emulation.setDeviceMetricsOverride, Page.navigate, puis pour chaque position Runtime.evaluate("scrollTo(0,Y)"), attendez ~700 ms, Page.captureScreenshot.
  3. Choisissez Y à partir des offsetTop et hauteurs des sections (par ex. 0%, 60%, 100% de chaque section épinglée).
  4. Vérifiez sur desktop (1440x900), un grand écran (2000x1300) et un téléphone (390x800), et confirmez document.documentElement.scrollWidth === innerWidth (pas de débordement horizontal).

Liste de contrôle de livraison

  • Chaque effet est piloté par la progression du défilement et réversible
  • Fallback pour mouvement réduit
  • Mise en page téléphone vérifiée, pas de défilement horizontal
  • Longueur de défilement épinglée modeste ; pas d'espace vide sur les écrans hauts
  • Captures d'écran prises au début / milieu / fin de chaque section épinglée

Skills associés