Animations Framer Motion

VérifiéSûr

Créez des animations déclenchées par défilement et d'entrée avec Framer Motion. Idéal pour ajouter des animations, implémenter des révélations au scroll ou migrer depuis CSS/Intersection Observer.

Spar Skills Guide Bot
DeveloppementIntermédiaire
23/07/2026
Claude CodeCursorWindsurfCodex
#framer-motion#animation#react#scroll-animations#reduced-motion

Recommandé pour

Synthèse automatique

Cette skill guide l'implémentation d'animations React avec Framer Motion : révélations au scroll, entrées/sorties, listes décalées (stagger) et respect de prefers-reduced-motion via useReducedMotion.

Points forts

  • Fournit des variantes prêtes à l'emploi (fadeInUp, staggerContainer, staggerItem, heroEntrance) avec courbes d'accélération cohérentes
  • Intègre systématiquement useReducedMotion pour l'accessibilité dans chaque exemple
  • Couvre trois cas d'usage concrets : scroll (whileInView + viewport once), listes décalées et animations d'entrée sans déclencheur de scroll
  • Donne des chemins de fichiers explicites pour centraliser les variantes partagées

Limites

  • Le document est tronqué : la section « 4. Index-Based » est incomplète et les animations de sortie annoncées ne sont pas illustrées
  • Les chemins cités (apps/web/src/app/about/_components/variants.ts) sont spécifiques à un projet et devront être adaptés
  • Le titre mentionne le paquet motion v12+ alors que tous les imports utilisent framer-motion, ce qui peut prêter à confusion
Quand l'utiliser

À utiliser lorsqu'il faut ajouter ou harmoniser des animations d'entrée et de révélation au scroll dans une application React/Next.js existante.

Quand l'éviter

À éviter pour des animations purement CSS légères, des transitions de route complexes ou des projets hors React qui ne peuvent pas utiliser Framer Motion.

Analyse de sécurité

Sûr
Score qualité86/100

The skill only provides Framer Motion animation guidance and code examples. It does not instruct destructive actions, network access, credential handling, obfuscation, or safety bypasses. The declared tools are file-editing/search tools used for legitimate code changes.

Aucun point d'attention détecté

Comment cette analyse est faite

Exemples

Scroll reveal on a section
Add a scroll-triggered fade-in-up animation to the testimonials section using our shared fadeInUpVariants, with viewport once and reduced-motion support.
Staggered feature grid
Animate this feature grid so the cards stagger in on scroll, reusing staggerContainerVariants and staggerItemVariants.
Migrate Intersection Observer
Replace the Intersection Observer reveal logic in this component with Framer Motion whileInView, keeping the same timing and respecting prefers-reduced-motion.

name: framer-motion-animations description: Create scroll-triggered and entrance animations using Framer Motion (motion package). Use when adding animations, implementing scroll reveals, or migrating from CSS/Intersection Observer. allowed-tools: Read, Edit, Write, Grep, Glob

Framer Motion Animations Skill

This skill helps you implement consistent, accessible animations across the codebase using Framer Motion (motion package v12+).

When to Use This Skill

  • Adding scroll-triggered reveal animations
  • Implementing entrance/exit animations
  • Creating staggered list animations
  • Migrating from CSS/Intersection Observer to Motion
  • Ensuring accessibility with reduced motion support

Key Files

| File | Purpose | |------|---------| | apps/web/src/app/about/_components/variants.ts | Shared animation variants | | apps/web/src/components/animated-number.tsx | Number animation component |

Animation Variants

Standard Variants (in variants.ts)

import type { Variants } from "framer-motion";

// Base fade-in-up animation for section content
export const fadeInUpVariants: Variants = {
  hidden: { opacity: 0, y: 20 },
  visible: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.6, ease: [0.16, 1, 0.3, 1] },
  },
};

// Container variant for staggered children
export const staggerContainerVariants: Variants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: { staggerChildren: 0.1, delayChildren: 0.1 },
  },
};

// Individual stagger item
export const staggerItemVariants: Variants = {
  hidden: { opacity: 0, y: 20 },
  visible: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.5, ease: [0.4, 0, 0.2, 1] },
  },
};

// Hero entrance animation (faster, more dramatic)
export const heroEntranceVariants: Variants = {
  hidden: { opacity: 0, y: 24, scale: 0.98 },
  visible: {
    opacity: 1,
    y: 0,
    scale: 1,
    transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] },
  },
};

Usage Patterns

1. Scroll-Triggered Animation (Single Element)

import { motion, useReducedMotion } from "framer-motion";
import { fadeInUpVariants } from "./variants";

export const Section = () => {
  const shouldReduceMotion = useReducedMotion();

  return (
    <motion.div
      variants={shouldReduceMotion ? undefined : fadeInUpVariants}
      initial={shouldReduceMotion ? undefined : "hidden"}
      whileInView="visible"
      viewport={{ once: true, amount: 0.2 }}
    >
      {/* Content */}
    </motion.div>
  );
};

2. Staggered List Animation

import { motion, useReducedMotion } from "framer-motion";
import { staggerContainerVariants, staggerItemVariants } from "./variants";

export const FeatureGrid = () => {
  const shouldReduceMotion = useReducedMotion();

  return (
    <motion.div
      className="grid grid-cols-2 gap-6"
      variants={shouldReduceMotion ? undefined : staggerContainerVariants}
      initial={shouldReduceMotion ? undefined : "hidden"}
      whileInView="visible"
      viewport={{ once: true, amount: 0.2 }}
    >
      {features.map((feature) => (
        <motion.div
          key={feature.id}
          variants={shouldReduceMotion ? undefined : staggerItemVariants}
        >
          {/* Feature card */}
        </motion.div>
      ))}
    </motion.div>
  );
};

3. Entrance Animation (No Scroll Trigger)

import { motion, useReducedMotion } from "framer-motion";

export const HeroSection = () => {
  const shouldReduceMotion = useReducedMotion();

  // Custom entrance transition with delay
  const entranceTransition = (delay: number) =>
    shouldReduceMotion
      ? undefined
      : { duration: 1, delay, ease: [0.16, 1, 0.3, 1] as const };

  return (
    <motion.h1
      initial={shouldReduceMotion ? undefined : { opacity: 0, y: 32 }}
      animate={{ opacity: 1, y: 0 }}
      transition={entranceTransition(0.15)}
    >
      Headline
    </motion.h1>
  );
};

4. Index-Based Stagger (Manual Delays)

import { motion, useReducedMotion } from "framer-motion";

interface TimelineItemProps {
  index: number;
}

const TimelineItem = ({ index }: TimelineItemProps) => {
  const shouldReduceMotion = useReducedMotion();

  return (
    <motion.div
      initial={shouldReduceMotion ? undefined : { opacity: 0, y: 32 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, amount: 0.3 }}
      transition={
        shouldReduceMotion
          ? undefined
          : { duration: 0.5, delay: index * 0.15, ease: [0.4, 0, 0.2, 1] }
      }
    >
      {/* Content */}
    </motion.div>
  );
};

5. Number Animation with Viewport Trigger

import { motion, useReducedMotion } from "framer-motion";
import { AnimatedNumber } from "@web/components/animated-number";
import { useState } from "react";
import { staggerItemVariants } from "./variants";

const StatItem = ({ value }: { value: number }) => {
  const shouldReduceMotion = useReducedMotion();
  const [isInView, setIsInView] = useState(false);

  return (
    <motion.div
      variants={shouldReduceMotion ? undefined : staggerItemVariants}
      onViewportEnter={() => setIsInView(true)}
      viewport={{ once: true }}
    >
      {isInView ? <AnimatedNumber value={value} /> : <span>0</span>}
    </motion.div>
  );
};

Accessibility

Always use useReducedMotion() to respect user preferences:

import { useReducedMotion } from "framer-motion";

const Component = () => {
  const shouldReduceMotion = useReducedMotion();

  // When reduced motion is preferred:
  // - Pass undefined to variants prop
  // - Pass undefined to initial prop
  // - Pass undefined to transition prop
  // - Skip CSS keyframe animations
};

When to Use CSS vs Motion

| Use Case | Recommendation | |----------|----------------| | Scroll-triggered reveals | Motion (whileInView) | | Entrance animations | Motion (initial/animate) | | Staggered lists | Motion (staggerChildren) | | Hover states | CSS (Tailwind transition-*) | | Infinite loops (background effects) | CSS keyframes | | Simple state transitions | CSS (transition-all) |

Easing Functions

Standard easing curves used in the codebase:

| Name | Value | Use Case | |------|-------|----------| | Smooth decelerate | [0.16, 1, 0.3, 1] | Hero entrances, dramatic reveals | | Standard ease | [0.4, 0, 0.2, 1] | General purpose animations |

Viewport Options

viewport={{
  once: true,      // Only animate once (recommended)
  amount: 0.2,     // Trigger when 20% visible
  // amount: 0.3,  // Trigger when 30% visible (for smaller items)
}}

File Organization

Variants file naming: Use variants.ts (industry standard)

src/app/about/
├── _components/
│   ├── variants.ts           # Shared animation variants
│   ├── hero-section.tsx      # Uses variants
│   ├── stats-section.tsx     # Uses variants + AnimatedNumber
│   └── timeline-section.tsx  # Uses variants

Migration from CSS/Intersection Observer

When migrating existing animations:

  1. Remove useState(isVisible) + useEffect with IntersectionObserver
  2. Remove ref passed to section element
  3. Add motion.div with whileInView
  4. Add useReducedMotion() check
  5. Import variants from shared file

Before (Intersection Observer):

const [isVisible, setIsVisible] = useState(false);
const sectionRef = useRef<HTMLDivElement>(null);

useEffect(() => {
  const observer = new IntersectionObserver(
    ([entry]) => { if (entry.isIntersecting) setIsVisible(true); },
    { threshold: 0.2 }
  );
  if (sectionRef.current) observer.observe(sectionRef.current);
  return () => observer.disconnect();
}, []);

return (
  <div ref={sectionRef} className={isVisible ? "animate-fade-in" : "opacity-0"}>

After (Motion):

const shouldReduceMotion = useReducedMotion();

return (
  <motion.div
    variants={shouldReduceMotion ? undefined : fadeInUpVariants}
    initial={shouldReduceMotion ? undefined : "hidden"}
    whileInView="visible"
    viewport={{ once: true, amount: 0.2 }}
  >

Validation Checklist

When implementing animations:

  • [ ] Uses useReducedMotion() for accessibility
  • [ ] Passes undefined to variants/initial/transition when reduced motion preferred
  • [ ] Uses shared variants from variants.ts where applicable
  • [ ] Uses viewport={{ once: true }} for scroll-triggered animations
  • [ ] Keeps hover states as CSS transitions (not Motion)
  • [ ] Uses CSS keyframes for infinite/background animations

Related Files

  • apps/web/CLAUDE.md - Web app conventions
  • apps/web/src/app/about/_components/variants.ts - Animation variants
  • apps/web/src/components/animated-number.tsx - Number animation component

Du fichier au premier essai

Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.

Consulter la source et ses fichiers annexes

Ce téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.

1. Télécharger le fichier

Télécharger SKILL.md

Depuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.

Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.

mkdir -p '.skill-downloads/framer-motion-animations-mrx3xxnw' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/framer-motion-animations-mrx3xxnw/download' --output '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md.part' && mv '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md.part' '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md'

2. Vérifier les prérequis

Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.

Outils déclarés par l’auteur (à vérifier dans votre agent) : Read, Edit, Write, Grep, Glob

Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.

Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.

3. Charger la skill

Après vérification, copiez le dossier complet dans le projet avec l’une des commandes ci-dessous, puis ouvrez une nouvelle session de l’outil. La commande s’arrête si un dossier du même nom existe déjà : comparez les fichiers avant de le remplacer.

Claude Code
test -f '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md' && test -s '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/framer-motion-animations' && cp -R '.skill-downloads/framer-motion-animations-mrx3xxnw' '.claude/skills/framer-motion-animations'

Cursor
test -f '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md' && test -s '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/framer-motion-animations' && cp -R '.skill-downloads/framer-motion-animations-mrx3xxnw' '.cursor/skills/framer-motion-animations'

Codex
test -f '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md' && test -s '.skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/framer-motion-animations' && cp -R '.skill-downloads/framer-motion-animations-mrx3xxnw' '.agents/skills/framer-motion-animations'

OpenSkills

OpenSkills doit déjà être installé. La procédure locale install/read est contrôlée avec OpenSkills 1.5.0, qui exige Node.js ≥ 20.6.0. Aucun slug du catalogue n’est résolu automatiquement.

Installation officielle d’OpenSkills
openskills install './.skill-downloads/framer-motion-animations-mrx3xxnw'

openskills read 'framer-motion-animations-mrx3xxnw'

La lecture doit afficher le contenu du fichier installé et son dossier de base. Elle ne lance ni la skill ni ses dépendances.

Pour un agent qui lit AGENTS.md, synchronisez ensuite l’index. Cette commande modifie AGENTS.md : relisez le diff avant de l’utiliser.

openskills sync

Mode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.

4. Faire un premier essai

Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :

Lis .skill-downloads/framer-motion-animations-mrx3xxnw/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.

Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.

Skills similaires