Что такое prefers-reduced-motion — и почему «меньше движения» не значит «без анимаций»

В 2013 году вышла iOS 7. Обои с параллаксом, приложения, которые вылетают из иконки с зумом. Красиво. И вместе с этим в настройках появился переключатель «Уменьшить движение» — чтобы всё это можно было выключить.
Сегодня такая настройка есть в каждой системе. А сайт видит её одной строкой CSS — prefers-reduced-motion.
Смотри, где подвох. Первая реакция разработчика — «выключу все анимации, и дело с концом». Инженер WebKit Джеймс Крейг ещё в 2017-м предупреждал: так ты только сделаешь сайт скучным. Убирать нужно не всё движение, а конкретные виды, от которых человеку физически плохо.
Что это такое
prefers-reduced-motion — медиа-запрос. У него два значения:
no-preference— человек ничего не просил;reduce— в системе включено «Уменьшить движение».
Где человек это включает:
- iPhone: «Настройки» → «Универсальный доступ» → «Движение»;
- Android 9+: «Специальные возможности» → «Удалить анимации»;
- Windows 11: «Специальные возможности» → «Визуальные эффекты» → «Эффекты анимации»;
- macOS: «Универсальный доступ» → «Уменьшить движение».
Браузер передаёт этот выбор странице. Chrome, Firefox и Safari понимают запрос уже много лет.
Зачем это людям
Главная причина — вестибулярные нарушения: проблемы внутреннего уха и тех частей мозга, что отвечают за равновесие. Глаза видят, что всё едет, а тело стоит на месте. Мозг получает противоречие — и человека укачивает, как в машине.
Это не редкость. В исследовании Johns Hopkins 2009 года тест на равновесие показал нарушения вестибулярной функции у 35,4% взрослых американцев старше 40 лет. В пояснениях к WCAG описаны реакции на лишнее движение: тошнота, мигрень, иногда нужно лечь и отлежаться.
А кто-то включает настройку просто потому, что движение отвлекает. Это тоже законная причина.
Какое движение укачивает, а какое можно оставить
В той же статье WebKit собраны типичные триггеры:
- зум и масштабирование — ощущение, что летишь вперёд или назад;
- вращение и спирали;
- движение с разной скоростью или в разные стороны — классический параллакс;
- сдвиг плоскостей — плоские карточки, которые поворачиваются в объёме;
- движение на периферии — фон шевелится, пока ты читаешь текст.
Что обычно безопасно:
- плавное появление через прозрачность;
- смена цвета;
- то, чем человек управляет сам: прокрутка пальцем, щипок для зума.
Отсюда правило: при reduce не удаляй анимацию, а замени её. Карточка не вылетает снизу, а спокойно проявляется на месте.
Как это учесть на сайте
В CSS — одним медиа-запросом:
.card {
animation: slide-up 0.5s ease both;
}
@media (prefers-reduced-motion: reduce) {
.card {
animation-name: fade-in;
}
html {
scroll-behavior: auto;
}
}
Вторая часть отключает плавную прокрутку по якорю. Это тоже движение, которое запустил не палец человека.
В JavaScript — для каруселей, автовидео и canvas-эффектов:
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!reduce) {
startParallax();
}
Настройку человек может переключить, не закрывая вкладку. Чтобы эффект остановился сразу, подпишись на изменение — в статье WebKit так и сделано:
const query = window.matchMedia('(prefers-reduced-motion: reduce)');
query.addEventListener('change', () => {
if (query.matches) stopParallax();
});
И отдельно про то, что запускается само, без действия человека: автокарусели, фоновые видео, бегущие строки. Для них в WCAG есть другой критерий — 2.2.2 «Пауза, остановка, скрытие», уровня A, то есть базовый. Если такое движение длится дольше пяти секунд и идёт рядом с другим контентом, человек должен уметь его остановить — даже если никаких настроек не включал.
В Tailwind есть варианты motion-safe: и motion-reduce: — первый добавляет анимацию только тем, кто не просил её убрать. Так не приходится потом «откатывать» каждое движение. Чем такие классы отличаются от ручного CSS — в статье Tailwind или CSS.
А вот важная штука для тех, кто собирает интерфейсы с ИИ. Популярная библиотека Motion (бывшая Framer Motion) по умолчанию настройку не учитывает: у MotionConfig значение reducedMotion равно never. Одна обёртка это исправляет:
import { MotionConfig } from 'motion/react';
export function App({ children }) {
return <MotionConfig reducedMotion="user">{children}</MotionConfig>;
}
С "user" библиотека отключает анимации сдвига и раскладки, но оставляет прозрачность и цвет фона. Ровно та замена, о которой выше.
Проверить без смены системных настроек можно в Chrome: DevTools → More tools → Rendering → «Emulate CSS media feature prefers-reduced-motion» → reduce. Особенно стоит пройтись по лендингу: анимаций на первом экране там обычно больше всего.
Похожая настройка есть и для цвета — режим forced colors, в котором Windows перекрашивает сайт палитрой человека.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.
А если без анимации интерфейс станет непонятным?
Тогда не удаляй её, а упрости. WebKit советует: если движение несёт смысл — например, показывает, куда улетел товар, — замени его на простой вариант или другой визуальный знак.
Это обязательное требование?
Критерий WCAG 2.3.3 «Анимация от взаимодействий» — уровень AAA, самый строгий. Обязательным его обычно не считают. Но стоит это одного медиа-запроса, а человеку экономит приступ тошноты.
Можно ли дать переключатель прямо на сайте?
Да, и WCAG приводит это как пример: одна кнопка на весь сайт отключает необязательные анимации. В Motion для этого есть значения reducedMotion="always" и "never" — их можно выставлять по настройке в профиле человека.
Нужно ли убирать все transition?
Нет. Смена цвета кнопки при наведении или мягкое появление подсказки никого не укачивают. Трогай крупное движение: зум, параллакс, вылеты через весь экран.





