Chakra UI предоставляет гибкую систему для работы с анимациями и
переходами компонентов. Основой является компонент motion
из интеграции с Framer Motion, который позволяет
создавать плавные анимации с минимальным количеством кода и без
существенного ущерба для производительности.
shouldForwardProp и ограничение перерисовокПри работе с анимациями важно контролировать, какие свойства
передаются внутрь DOM. Компоненты Chakra UI позволяют использовать
shouldForwardProp, чтобы исключать ненужные пропсы, которые
могут вызывать лишние ререндеры:
import { chakra, shouldForwardProp } from "@chakra-ui/react";
import { motion, isValidMotionProp } from "framer-motion";
const MotionBox = chakra(motion.div, {
shouldForwardProp: (prop) => isValidMotionProp(prop) || shouldForwardProp(prop),
});
Такой подход снижает нагрузку на браузер и предотвращает ненужные обновления.
Для плавных анимаций важно использовать CSS-свойства,
поддерживаемые GPU, такие как transform и
opacity. Chakra UI позволяет напрямую задавать анимации
через animate:
<MotionBox
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4, ease: "easeOut" }}
/>
Использование transform: translateY вместо
top или margin-top позволяет избежать
перерисовки layout и снижает нагрузку на главный поток браузера.
transition и layoutChakra UI и Framer Motion поддерживают детальную настройку фреймрейта анимаций:
<MotionBox
layout
transition={{ type: "spring", stiffness: 300, damping: 30 }}
/>
layout инициирует анимацию изменения размеров или
положения элементов.spring с корректными параметрами уменьшает количество
кадров, делая анимацию плавной, но менее затратной по
производительности.AnimatePresence для динамических компонентовКомпонент AnimatePresence управляет монтированием и
размонтированием элементов с анимацией, предотвращая скачки и лишние
перерисовки:
import { AnimatePresence, motion } from "framer-motion";
<AnimatePresence>
{isVisible && (
<MotionBox
key="modal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
Контент модального окна
</MotionBox>
)}
</AnimatePresence>
AnimatePresence гарантирует, что элемент полностью
отрисован до завершения анимации выхода, что снижает визуальные
артефакты.
shouldReduceMotion для адаптации под системные
настройкиДля улучшения производительности и доступности Chakra UI
предоставляет хук usePrefersReducedMotion:
import { usePrefersReducedMotion, Box } from "@chakra-ui/react";
const Component = () => {
const prefersReducedMotion = usePrefersReducedMotion();
return (
<Box
as={motion.div}
animate={prefersReducedMotion ? {} : { opacity: 1, y: 0 }}
initial={{ opacity: 0, y: -20 }}
transition={{ duration: 0.5 }}
/>
);
};
Эта техника отключает или упрощает анимации для пользователей с настройками сокращения движения, одновременно снижая нагрузку на рендеринг.
Для сложных анимаций рекомендуется:
React.lazy или условный рендеринг.React.memo
для анимируемых компонентов, чтобы перерисовка происходила только при
изменении пропсов.const AnimatedBox = React.memo(({ children, isVisible }) => (
<MotionBox
initial={{ opacity: 0 }}
animate={{ opacity: isVisible ? 1 : 0 }}
transition={{ duration: 0.3 }}
>
{children}
</MotionBox>
));
Слишком глубокая вложенность анимированных компонентов увеличивает нагрузку на рендеринг. Оптимально:
const containerVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1, transition: { staggerChildren: 0.1 } },
};
const childVariants = {
hidden: { y: 20, opacity: 0 },
visible: { y: 0, opacity: 1 },
};
<MotionBox variants={containerVariants} initial="hidden" animate="visible">
<MotionBox variants={childVariants}>Элемент 1</MotionBox>
<MotionBox variants={childVariants}>Элемент 2</MotionBox>
</MotionBox>
Такой подход снижает количество одновременных анимаций и улучшает FPS.
will-change и GPU-активацияChakra UI позволяет напрямую задавать стиль willChange
через sx или проп __css:
<MotionBox
sx={{ willChange: "transform, opacity" }}
animate={{ transform: "translateY(0)", opacity: 1 }}
initial={{ transform: "translateY(-20px)", opacity: 0 }}
/>
Предварительное указание браузеру, какие свойства будут анимироваться, позволяет задействовать GPU заранее и уменьшить задержки.
motion.custom для Chakra-компонентовМожно создавать обертки motion для всех базовых
компонентов Chakra UI (Box, Flex,
Button) с целью повторного использования анимационных
настроек, что снижает дублирование кода и упрощает управление
производительностью:
import { chakra, Box } from "@chakra-ui/react";
import { motion, isValidMotionProp } from "framer-motion";
const MotionButton = chakra(motion(Button), {
shouldForwardProp: (prop) => isValidMotionProp(prop) || prop === "onClick",
});
Это позволяет стандартизировать анимации и уменьшить количество ререндеров при масштабировании интерфейса.