Справочник · CSS
transition: плавный переход между состояниями
Свойство transition плавно меняет значение CSS-свойства, когда оно переходит из одного состояния в другое: при наведении, фокусе, добавлении класса. В короткой записи указывают свойство, длительность, функцию времени и задержку: transition: background-color .2s ease.
transition: свойство длительность функция задержка.- Перечисляй конкретные свойства, а не
all. - Для интерфейса обычно хватает 150–250 мс.
- Плавнее всего анимируются
transformиopacity. - Между
display: noneиblockобычный переход не работает.
Минимальный пример
.button {
background-color: #2a62d9;
transition: background-color .2s ease, transform .2s ease;
}
.button:hover {
background-color: #1f4fb8;
transform: translateY(-2px);
}При наведении фон темнеет, а кнопка приподнимается — плавно за 0,2 секунды. transition пишут в обычном состоянии элемента, а не в :hover: тогда анимация работает и при наведении, и при уходе курсора.
Части свойства
| Свойство | Что задаёт | Пример |
|---|---|---|
transition-property | какое свойство анимировать | opacity, transform |
transition-duration | длительность | .2s, 200ms |
transition-timing-function | характер ускорения | ease, ease-out |
transition-delay | задержка перед стартом | .1s |
В короткой записи первое время — длительность, второе — задержка. Несколько переходов перечисляют через запятую, у каждого свои параметры.
Функции времени
| Значение | Движение | Когда |
|---|---|---|
ease | мягкий старт, быстрая середина, плавная остановка | по умолчанию, универсально |
ease-out | быстрый старт, плавная остановка | появление элементов |
ease-in | плавный старт, резкая остановка | исчезновение |
linear | постоянная скорость | вращение, прогресс |
cubic-bezier(.2, .8, .2, 1) | своя кривая | фирменное движение |
steps(4) | скачками | покадровая анимация |
Что можно анимировать
Анимируются свойства с промежуточными значениями: цвета, размеры, отступы, opacity, transform, тени. Нельзя плавно перейти между значениями без середины: display: none ↔ block, visibility переключается скачком (но умеет ждать окончания перехода), height: auto — нельзя анимировать к auto в большинстве браузеров.
/* показать и спрятать плавно, сохранив доступность */
.tooltip {
opacity: 0;
visibility: hidden;
transition: opacity .2s ease, visibility 0s linear .2s;
}
.tooltip.is-visible {
opacity: 1;
visibility: visible;
transition: opacity .2s ease, visibility 0s;
}Связка opacity и visibility с задержкой даёт плавное исчезновение, и при этом скрытый элемент не ловит клики и фокус. Современные браузеры начинают поддерживать переход к display: none через transition-behavior: allow-discrete, но для широкой совместимости надёжнее приём выше.
Производительность: что анимировать
/* плавно: не трогает раскладку */
.card { transition: transform .2s ease, opacity .2s ease; }
.card:hover { transform: translateY(-4px); }
/* дёргается: браузер пересчитывает раскладку каждый кадр */
.card { transition: top .2s, width .2s; }transform и opacity браузер анимирует отдельно от раскладки, часто на видеокарте — они плавны даже на слабых телефонах. Изменение width, height, top, margin заставляет пересчитывать положение соседей на каждом кадре. Вместо top двигай через translate, вместо width — scale, где это возможно.
Почему не стоит писать transition: all
transition: all .3s анимирует любое изменение — включая размеры при смене раскладки, цвет фокуса, свойства, которые изменятся позже при доработке. Компонент начинает неожиданно «плыть». Перечисли то, что действительно должно двигаться: transition: background-color .2s, box-shadow .2s.
Какую длительность выбрать
Реакция на наведение и нажатие — 100–200 мс: дольше, и интерфейс кажется медленным. Появление панелей и раскрытие блоков — 200–300 мс. Большие перемещения по экрану — до 400–500 мс. Исчезновение обычно делают чуть быстрее появления.
Уважай просьбу о меньшем движении
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
transition-duration: .01ms !important;
animation-duration: .01ms !important;
}
}Некоторым людям от движения на экране становится плохо. В системе есть настройка «уменьшить движение», и CSS её видит. Отключай необязательные переходы — элементы всё равно меняют состояние, просто сразу.
transition или animation
Переход между двумя состояниями по событию: наведение, фокус, класс. Простой и предсказуемый.
Сценарий из нескольких шагов через @keyframes: может запускаться сам, повторяться, идти по кругу.
Частые ошибки
- Пишут transition только в
:hover, и при уходе курсора всё возвращается скачком. - Используют
transition: allдля сложного компонента. - Анимируют width, height и top вместо transform.
- Ждут плавного перехода от
display: none. - Делают реакцию кнопки дольше 300 мс, и интерфейс кажется тормозящим.
Доступность
Учитывай prefers-reduced-motion: необязательные переходы отключай. Не прячь информацию так, что она видна только в середине анимации. Мигание чаще трёх раз в секунду опасно для людей с фоточувствительной эпилепсией — с transition такого почти не бывает, но с повторяющимися эффектами будь осторожен.
Поддержка браузерами
transition и все его части поддерживаются всеми браузерами без префиксов. transition-behavior: allow-discrete и анимация к height: auto через interpolate-size — новые возможности, доступные пока не во всех браузерах.
Практика
Сделай карточку, которая при наведении поднимается на 4px и получает тень за 200 мс, и подсказку, которая плавно появляется и исчезает, при этом в скрытом состоянии не ловит клики. Отключи переходы для тех, кто просил меньше движения.
Показать решение
.card { transition: transform .2s ease, box-shadow .2s ease; }
.card:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgb(0 0 0 / .12); }
.tip { opacity: 0; visibility: hidden; transition: opacity .2s, visibility 0s .2s; }
.tip.is-visible { opacity: 1; visibility: visible; transition: opacity .2s, visibility 0s; }
@media (prefers-reduced-motion: reduce) {
.card, .tip { transition: none; }
}Частые вопросы
Почему transition не работает?
Свойство не меняется, transition написан только в :hover, свойство нельзя анимировать (display) или указано не то имя свойства.
Можно ли плавно показать элемент с display: none?
Обычным transition — нет. Используй opacity вместе с visibility или новый transition-behavior: allow-discrete там, где он поддерживается.
Какие свойства лучше анимировать?
transform и opacity: они не заставляют пересчитывать раскладку и идут плавно даже на слабых устройствах.
Какую длительность выбрать?
150–250 мс для реакций на наведение и нажатие, 200–300 мс для появления панелей.
Где писать transition: в :hover или в обычном состоянии?
В обычном. Тогда переход сработает в обе стороны — при наведении и при уходе курсора.
Источники
Практикум по теме
- Меньше движения для тех, кто просил — Часть людей включает в системе настройку «уменьшить движение». Сайт может это уважать.