Гид по технологиям

Framer Motion: создание анимаций в React

7 min read Frontend Обновлено 09 Jan 2026
Framer Motion: анимации в React
Framer Motion: анимации в React

Логотип Framer Motion на градиентном фоне

Анимация — ключевая часть почти любого современного веб‑приложения. Однако её трудно сделать правильно: нужно учитывать перформанс, доступность, поведение при разных состояниях и интеграцию со стейтом. Framer Motion — библиотека для React, которая значительно упрощает эти задачи и делает код чище и предсказуемее.

Как работает Framer Motion

Framer Motion использует специальные motion‑компоненты для анимации. Каждому HTML/SVG‑элементу соответствует эквивалентный motion‑элемент с пропсами для жестов и анимаций. Например, обычный HTML‑div выглядит так:

 

А эквивалент в Framer Motion — так:

   

Motion‑компоненты поддерживают проп animate, который запускает анимацию при изменении значений. Для более сложных сценариев используют хук useAnimate и локальные ref.

Ключевые термины в одной строке:

  • motion‑компонент — компонент, который рендерит HTML/SVG и принимает анимационные пропсы.
  • variants — набор предопределённых состояний анимации.
  • AnimatePresence — компонент, разрешающий exit‑анимации перед удалением из DOM.

Требования и подготовка

Перед началом убедитесь, что на машине установлены Node.js и менеджер пакетов (npm или Yarn), и вы понимаете основы React. Проект в примере доступен на GitHub. Используйте ветку starter‑files как шаблон, а final‑files — для окончательного демо. Есть также live‑demo проекта.

Откройте терминал и выполните:

git clone git@github.com:makeuseofcode/framer-motion-app.git  
cd framer-motion-app  
yarn  
yarn dev  

Открыв localhost:5173 в браузере, вы увидите стартовый экран:

Экран проекта по умолчанию с макетом и кнопкой

Простая анимация: кнопка с эффектом hover

Создадим первую анимацию: кнопка, которая увеличивается при наведении и возвращается в исходное состояние при уходе курсора.

Откройте файл src/App.jsx. В нём есть функциональный компонент, который импортирует и рендерит компонент Button, передавая проп text:

    

Animated Button

    
Move your mouse over the button to see the effect
    

В компоненте Button импортируйте motion из framer‑motion:

import { motion } from "framer-motion"  

Замените обычный button на motion.button и добавьте проп whileHover с желаемыми значениями:

  
  
{text}  
  

Теперь кнопка анимируется при наведении курсора.

Важно: Framer Motion удобен тем, что идеально интегрируется со стейтом React — вы можете анимировать значения, основанные на пропсах и локальном состоянии, и при этом код остаётся декларативным.

Анимация модального окна: Backdrop и Modal

Давайте разберём более сложный пример — модальное окно с backdrop, включающее входную и выходную анимации.

В Backdrop.jsx импортируйте motion и создайте компонент с пропами onClick и children. Верните motion.div с классом backdrop и слушателем onClick:

export default function Backdrop() {  
    return (<>  
          
          
    )  
}  

Добавим три ключевых пропа: initial, animate и exit — это исходное состояние, целевое состояние и состояние при выходе соответственно. Также установим transition.duration = 0.34 с:

export default function Backdrop ({onClick, children}){  
    return (<>  
          
            {children}  
          
    )  
}  

Backdrop служит обёрткой для Modal: клик по backdrop закрывает модалку. В Modal.jsx импортируйте motion и Backdrop. Компонент принимает closeModal и text.

Создайте объект variants с предопределёнными состояниями:

    const variants = {  
        initial: {  
            y: "-200%",  
            opacity: 1,  
        },  
        visible: {  
            y: "50%",  
            transition: {  
                duration: 0.1,  
                type: "spring",  
                damping: 32,  
                stiffness: 500  
            }  
        },  
        exit: {  
            y: "200%",  
        }  
    }  

Верните motion.div, обёрнутый Backdrop, с пропом variants:

  
     e.stopPropagation()}  
        className="modal"  
        variants={variants}  
        initial='initial'  
        animate='visible'  
        exit='exit'  
    >  
        {text}  
      
  

Variants — это удобный способ описать все состояния компонента декларативно.

Показать/скрыть модалку и AnimatePresence

В App.jsx импортируйте useState и Modal:

import { useState } from "react";  
import Modal from "./components/Modal";  

Создайте состояние modalOpen и функцию closeModal:

const [modalOpen, setModalOpen] = useState(false);  

function closeModal() {  
    setModalOpen(false)  
}  

Вставьте условный рендер модалки:

{modalOpen &&   

Если вы заметите, то при простом условном рендере React удаляет компонент из DOM без exit‑анимации. Чтобы разрешить анимации выхода, используйте AnimatePresence. Импортируйте его:

import {AnimatePresence} from 'framer-motion';  

Обёрните Modal в AnimatePresence и установите initial={false} и mode=”wait”:

  
    {modalOpen && }  

AnimatePresence даёт Framer Motion время завершить exit‑анимацию перед удалением элемента из DOM.

Анимация элементов при прокрутке

Framer Motion умеет запускать анимацию, когда элемент появляется в области просмотра, с помощью пропа whileInView. В ScrollElement.jsx импортируйте motion и замените div на motion.div:

  
    Scroll Element  
  

viewport={{ once: true }} гарантирует, что анимация выполнится только один раз при первом вхождении в экран.

В App.jsx можно рендерить несколько таких элементов динамически. Например:

let scrollElementCount=14;  

{[...Array(scrollElementCount)].map((x, i) => )}  

Теперь элементы будут анимироваться по мере прокрутки.

Альтернативы Framer Motion

Framer Motion не единственный инструмент. Вот основные альтернативы и сценарии, когда стоит рассмотреть их:

  • React Spring — декларативная библиотека с физически корректными пружинными анимациями; хорошо подходит для сложных физических движений.
  • CSS‑анимации / transition — нативная поддержка браузера, минимальная зависимость, хорошая производительность для простых эффектов.
  • GreenSock (GSAP) — очень мощен для сложных и синхронизированных анимаций, но добавляет контейнер синтаксиса вне React‑конвенций.

Выбор зависит от целей: если вам нужна тесная интеграция с React‑стейтом и удобные lifecycle‑эффекты — Framer Motion часто удобнее. Если важна минимизация зависимостей — выбирайте CSS или Web Animations API.

Почему анимации улучшают UX

Анимации помогают пользователю понять, что произошло: появились новые элементы, данные обновились или произошло подтверждение действия. Они делают интерфейс «живым» и понятным. Главное — использовать умеренно и предсказуемо: слишком много эффектов отвлекает и замедляет взаимодействие.

Практические рекомендации и чек‑листы

Чек‑лист для разработчика:

  • Используйте motion‑компоненты вместо прямых манипуляций с DOM.
  • Выносите варианты состояний в const variants = {…} для читаемости.
  • Применяйте AnimatePresence для компонентов, которым нужен exit.
  • Проверяйте перформанс: избегайте анимации свойств, которые приводят к reflow (например, top/left); отдавайте предпочтение transform и opacity.
  • Тестируйте на мобильных устройствах и низкой мощности.

Чек‑лист для дизайнера:

  • Определите цель каждой анимации (подсказка, подтверждение, фокус).
  • Ограничьте продолжительность анимаций для основных действий (обычно 100–400 мс для интерфейсных переходов).
  • Укажите easing (spring/linear/cubic) и ожидаемое поведение.

Чек‑лист для QA:

  • Проверить входные и выходные анимации на всех поддерживаемых браузерах.
  • Убедиться, что exit анимации выполняются перед удалением DOM элементов.
  • Проверить взаимодействие с клавиатурой и экранными читалками.

Accessibility и настройки для пользователей

Important: всегда уважайте системные настройки пользователя. Если у пользователя включён prefers‑reduced‑motion, отключайте ненужные анимации или упрощайте их.

Пример проверки prefers‑reduced‑motion в CSS/JS:

  • CSS: @media (prefers-reduced-motion: reduce) { / упрощённые стили / }
  • JS: const prefersReduce = window.matchMedia(‘(prefers-reduced-motion: reduce)’).matches;

Если prefersReduce === true, переключайте значения анимаций на статические состояния или устанавливайте transition.duration = 0.

Когда анимации вредны — контрпримеры

  • Длительные декоративные анимации на главной странице замедляют восприятие и увеличивают TTI (Time To Interactive).
  • Сложные последовательные анимации могут мешать пользователям с когнитивными ограничениями.
  • Анимация layout‑свойств (width/height/top) на больших элементах приводит к сильному reflow и падению FPS.

Критерии приёмки

  • Все ключевые сценарии имеют входную и выходную анимацию, если это необходимо.
  • Exit‑анимации завершаются до удаления компонента из DOM (AnimatePresence обеспечивает это).
  • Анимации не ухудшают перформанс (проверено на мобильных устройствах).
  • Пользователь с prefers‑reduced‑motion вынужден не чувствовать лишних движений.
  • Компоненты воспроизводимы и имеют понятные variants.

Быстрый чек‑шит (cheat sheet)

  • Для hover: whileHover={{ scale: 1.05 }}
  • Для tap: whileTap={{ scale: 0.95 }}
  • Для входа/выхода: initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
  • Для появлений поスクроллу: whileInView + viewport={{ once: true }}
  • Для последовательных анимаций: useAnimation + controls.start(…)

Пример использования AnimatePresence с задержкой:


  {isOpen && (
    
      ...
    
  )}

Тестовые сценарии и критерии приёмки

  • Нажать кнопку «Show Modal» — модалка появляется с ожидаемой анимацией.
  • Нажать фон (backdrop) — модалка выходит с анимацией и затем удаляется из DOM.
  • Навести курсор на кнопку — whileHover работает и возвращает элемент в исходное состояние при уходе.
  • Прокрутить страницу — элементы с whileInView анимируются единожды.
  • Включён prefers‑reduced‑motion — анимации не выполняются или используются минимальные переходы.

Краткая справка (глоссарий)

  • motion — базовый конструкт для анимируемых компонентов.
  • variants — набор именованных состояний анимации.
  • AnimatePresence — компонент для корректных exit‑анимаций.
  • whileInView — запускает анимацию при вхождении в viewport.

Заключение

Framer Motion даёт удобный декларативный API для анимаций в React, упрощая работу с интеракциями, модальными окнами и анимациями при прокрутке. Он помогает интегрировать анимации с React‑стейтом и уменьшает количество вспомогательного кода. В то же время важно соблюдать принципы производительности и доступности: отдавайте предпочтение transform/opacity, уважайте prefers‑reduced‑motion и тестируйте на целевых устройствах.

Короткие рекомендации:

  • Начинайте с простых эффектов и выносите состояния в variants.
  • Используйте AnimatePresence для выхода компонентов.
  • Тестируйте перформанс и доступность.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство