Respect для prefers-reduced-motion

Современные веб-приложения активно используют анимации для улучшения пользовательского опыта. Однако не все пользователи воспринимают движение одинаково. Некоторые испытывают дискомфорт или утомление при обильном использовании анимаций. CSS и JavaScript предоставляют возможность учитывать предпочтения пользователя через медиавыражение prefers-reduced-motion. Chakra UI встроенно поддерживает этот подход, позволяя создавать интерфейсы, которые уважают такие предпочтения.

Медиавыражение prefers-reduced-motion

prefers-reduced-motion — это CSS медиавыражение, которое сообщает о предпочтении пользователя к минимизации движений на экране:

@media (prefers-reduced-motion: reduce) {
  .animated-element {
    animation: none;
    transition: none;
  }
}

Значение reduce указывает, что пользователь предпочитает минимальные анимации. Это важно для accessibility и соответствия WCAG 2.1.

В Chakra UI можно использовать это выражение через хук usePrefersReducedMotion, что обеспечивает реактивное и декларативное управление анимациями внутри компонентов.

Хук usePrefersReducedMotion

Chakra UI предоставляет хук:

import { usePrefersReducedMotion } from "@chakra-ui/react";

const Component = () => {
  const prefersReducedMotion = usePrefersReducedMotion();

  return (
    <Box
      animation={prefersReducedMotion ? "none" : "fadeIn 2s ease-in"}
    >
      Контент с анимацией
    </Box>
  );
};

Особенности:

  • Возвращает булевое значение: true, если пользователь предпочитает минимальные анимации.
  • Позволяет динамически отключать или заменять анимации.
  • Интегрируется с любыми компонентами Chakra UI, которые используют CSS анимации или framer-motion.

Интеграция с компонентами Chakra UI и Framer Motion

Chakra UI тесно интегрирован с библиотекой framer-motion для создания анимаций. Чтобы учесть prefers-reduced-motion в анимированных компонентах, можно использовать свойство motionProps или условно применять анимацию:

import { Box, usePrefersReducedMotion } from "@chakra-ui/react";
import { motion } from "framer-motion";

const MotionBox = motion(Box);

const AnimatedComponent = () => {
  const prefersReducedMotion = usePrefersReducedMotion();

  return (
    <MotionBox
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={prefersReducedMotion ? { duration: 0 } : { duration: 1 }}
    >
      Анимационный компонент
    </MotionBox>
  );
};

Ключевые моменты:

  • transition можно полностью убрать или сократить продолжительность анимации.
  • initial и animate остаются, чтобы структура компонента не ломалась.
  • Поддержка prefers-reduced-motion повышает доступность интерфейса.

Глобальная настройка анимаций

Chakra UI позволяет задавать глобальные настройки анимаций через тему:

import { extendTheme } from "@chakra-ui/react";

const theme = extendTheme({
  styles: {
    global: (props) => ({
      "*": {
        transitionDuration: props.reduceMotion ? "0ms" : "250ms",
      },
    }),
  },
});

export default theme;

Здесь props.reduceMotion автоматически учитывает prefers-reduced-motion, позволяя централизованно управлять всеми анимациями.

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

  • Минимизировать движение для всех критичных компонентов: модальные окна, всплывающие уведомления, слайдеры.
  • Делать анимации условными: использовать usePrefersReducedMotion для динамического контроля.
  • Поддерживать fallback: если анимация отключена, компонент должен оставаться полностью функциональным и читаемым.
  • Тестировать интерфейс с отключенными анимациями: эмуляция через настройки браузера помогает проверить правильность работы.

Использование prefers-reduced-motion в Chakra UI позволяет создавать интерфейсы, которые одновременно современны и дружелюбны к пользователям с особыми потребностями, обеспечивая универсальную доступность без лишнего кода и сложности.