Моушн в интерфейсе: длительность, кривые, prefers-reduced-motion
Анимация в интерфейсе нужна не для красоты, а чтобы объяснять, что произошло: откуда появился элемент, куда он ушёл, что изменилось после действия. Разберём, какую длительность выбирать, чем отличаются кривые ускорения, что можно анимировать без просадки кадров и как не навредить людям, которым движение мешает.

Зачем интерфейсу движение
У анимации в продукте три полезные функции. Первая — связь состояний: когда карточка раскрывается в полноэкранный вид, движение показывает, что это тот же объект, а не новая страница. Вторая — обратная связь: кнопка, которая отзывается на нажатие, подтверждает, что действие принято. Третья — направление внимания: новое уведомление, плавно въехавшее сбоку, замечают быстрее, чем внезапно появившееся.
Всё, что не попадает в эти три категории, стоит проверять на необходимость. Декоративная анимация на каждом скролле, медленные появления блоков при прокрутке, подпрыгивающие иконки — всё это задерживает пользователя и со временем раздражает. Анимация, которую человек увидит сотню раз в день, должна быть почти незаметной.
Хороший тест: если отключить анимацию, станет ли непонятно, что произошло? Если да — движение несёт смысл. Если интерфейс читается так же, а ощущение просто «чуть скучнее», возможно, анимацию стоит сократить или сделать короче.
Длительность: короче, чем кажется
Большинство интерфейсных переходов укладываются в диапазон 100–400 мс. Ориентиры, которые повторяются в публичных гайдлайнах, в том числе в Material Design: микровзаимодействия вроде смены состояния кнопки или переключателя — 100–150 мс; появление небольших элементов, тултипов, выпадающих меню — 150–250 мс; крупные переходы — модальные окна, боковые панели, смена экранов — 250–400 мс.
Длительность зависит от расстояния и размера. Элемент, который проходит половину экрана, должен двигаться дольше, чем чекбокс, меняющий цвет. На мобильных устройствах переходы обычно короче, чем на планшетах, потому что расстояния меньше. На больших мониторах, наоборот, слишком быстрое перемещение через весь экран выглядит рывком.
Исчезновение почти всегда делают быстрее появления. Когда пользователь закрывает окно, он уже принял решение и не хочет ждать; уход за 150–200 мс при появлении за 250 мс ощущается естественно. То же касается отмены действия: возврат должен быть не медленнее исходного движения.
Анимация длиннее 500 мс в рабочем интерфейсе почти всегда воспринимается как задержка. Исключения — онбординг, пустые состояния, иллюстративные сцены, которые пользователь видит один раз.
- Микровзаимодействия: 100–150 мс.
- Небольшие элементы, меню, тултипы: 150–250 мс.
- Модальные окна, панели, экраны: 250–400 мс.
- Уход элемента — быстрее появления.

Кривые ускорения: почему не linear
В реальном мире объекты не начинают движение мгновенно на полной скорости и не останавливаются как вкопанные. Линейная анимация, linear, поэтому выглядит механической — она уместна только для бесконечных процессов вроде вращения индикатора загрузки или для изменения прозрачности.
Для большинства переходов используются три типа кривых. Ease-out (быстрый старт, плавное торможение) — для элементов, которые появляются на экране: они быстро реагируют и мягко встают на место. Ease-in (плавный старт, ускорение в конце) — для элементов, которые уходят с экрана. Ease-in-out — для перемещения элемента, который остаётся в поле зрения, например при перестановке карточек.
Стандартные ключевые слова CSS — ease, ease-in, ease-out — довольно мягкие. В дизайн-системах обычно задают собственные кривые через cubic-bezier(). Например, Material Design описывает «стандартную» кривую как cubic-bezier(0.2, 0, 0, 1) — резкий старт и долгое торможение. Такие кривые стоит вынести в токены, а не подбирать заново в каждом компоненте.
Пружинные анимации, которые дают небольшой перелёт и возврат, хороши для жестов и перетаскивания: они передают физику и отзывчивость. В интерфейсах с серьёзным контекстом — финансы, медицина, рабочие инструменты — перелёт стоит делать минимальным или обходиться без него. В CSS приблизить пружину можно функцией linear() с набором точек, в JS-библиотеках она обычно есть из коробки.
Что анимировать, чтобы не терять кадры
Плавной анимация выглядит при 60 кадрах в секунду, а значит, на подготовку каждого кадра у браузера около 16 мс. Если анимируемое свойство заставляет пересчитывать раскладку страницы, этого времени не хватает, и анимация дёргается — особенно на недорогих смартфонах.
Безопасные свойства — transform и opacity. Браузер может обработать их на этапе композитинга, не трогая раскладку и отрисовку. Перемещение через transform: translate() вместо top/left, масштабирование через scale() вместо width/height — базовое правило производительной анимации.
Анимация высоты — самая частая проблема, например у аккордеонов. Анимировать height от нуля до auto долгое время было нельзя в принципе. Сейчас в части браузеров появилась поддержка interpolate-size: allow-keywords и функции calc-size(), но пока их нет везде, надёжные варианты — анимация grid-template-rows от 0fr к 1fr или трансформация с последующей подстановкой высоты.
Свойство will-change стоит ставить точечно и только на время анимации. Если объявить его на десятках элементов заранее, браузер выделит под них отдельные слои и съест память, что ударит по производительности сильнее, чем сама анимация.
- Можно: transform, opacity, filter (с осторожностью).
- Избегать: width, height, top, left, margin, padding.
- Аккордеон: grid-template-rows 0fr → 1fr.
- will-change — только на время анимации.
prefers-reduced-motion: обязательная часть системы
Для части людей движение на экране — не украшение, а проблема. При вестибулярных нарушениях крупные перемещения, параллакс и зум могут вызывать головокружение и тошноту. Поэтому операционные системы дают настройку «Уменьшить движение», а браузеры передают её в CSS через медиазапрос prefers-reduced-motion: reduce.
Критерий WCAG 2.3.3 «Animation from Interactions» уровня AAA требует, чтобы анимацию, запускаемую взаимодействием, можно было отключить, если она не является необходимой. Даже если продукт ориентируется на уровень AA, учитывать эту настройку — дешёвый и правильный шаг.
Важно: «уменьшить» не значит «удалить всё». Анимация, которая объясняет смену состояния, может остаться, но в более мягкой форме: вместо выезда панели через весь экран — короткое растворение через opacity; вместо параллакса — статичный фон. Полностью стоит убирать автозапуск, бесконечные циклы, параллакс, крупные масштабирования и вращения.
Технически удобно задавать длительности через переменные и переопределять их в медиазапросе: @media (prefers-reduced-motion: reduce) { :root { --motion-distance: 0; } }. В JS ту же настройку можно прочитать через matchMedia('(prefers-reduced-motion: reduce)') и не запускать тяжёлые сцены.
Как оформить моушн в дизайн-системе
Чтобы анимация в продукте была консистентной, её нужно описать так же, как цвета и типографику. Минимальный набор: 3–4 токена длительности (например, duration-fast, duration-base, duration-slow), 3–4 кривые и таблица «какой паттерн какие токены использует».
Полезно описывать не отдельные анимации, а паттерны: появление тултипа, открытие модального окна, раскрытие аккордеона, перестановка элементов списка, загрузка контента. Для каждого — длительность, кривая, анимируемые свойства и поведение при уменьшенном движении. Тогда разработчику не нужно гадать по прототипу, а дизайнеру — объяснять одно и то же в каждой задаче.
Для передачи анимации в разработку прототипа в Figma часто недостаточно: в нём сложно увидеть точные значения кривых. Лучше дополнять прототип таблицей параметров или короткой записью экрана с подписанными значениями. А финальную проверку делать в браузере на реальном устройстве — с включённым и выключенным режимом уменьшения движения.
Частые вопросы
Какая длительность анимации оптимальна для интерфейса?
Для большинства переходов — от 100 до 400 мс: меньше для микровзаимодействий, больше для крупных переходов вроде модальных окон. Дольше 500 мс рабочая анимация уже воспринимается как задержка.
Какие CSS-свойства безопасно анимировать?
transform и opacity: их браузер обрабатывает без пересчёта раскладки. Анимация width, height, top, left и отступов чаще вызывает рывки.
Нужно ли полностью отключать анимацию при prefers-reduced-motion?
Не обязательно. Стоит убрать параллакс, автозапуск, крупные перемещения и зум, а смысловые переходы заменить мягким изменением прозрачности.

Пишем об UX/UI-дизайне: исследования, интерфейсы, дизайн-системы и доступность.


