CSS-анимации: примеры и готовый код
Соберите анимацию на @keyframes или возьмите готовую: появление, пульсация, загрузка, анимация кнопки при наведении.
@keyframes myAnimation {
0% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
.animated-element {
animation-name: myAnimation;
animation-duration: 1s;
animation-timing-function: ease;
animation-iteration-count: 1;
}
/* Сокращенная запись */
.animated-element {
animation: myAnimation 1s ease 1;
}Готовые анимации — кликните, чтобы загрузить в конструктор
Как сделать анимацию в CSS
Анимация собирается из двух частей. Сначала вы описываете кадры в правиле @keyframes: что происходит в начале и в конце. Потом подключаете их к элементу свойством animation. Имя и длительность обязательны, остальное по необходимости.
/* 1. описываем кадры */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 2. подключаем к элементу */
.card {
animation: fadeIn 0.5s ease both;
}Кадров может быть сколько угодно. Вместо from и to пишите проценты: 0%, 50%, 100%. Конструктор выше собирает такой код визуально: вы двигаете ползунки, а он отдаёт готовое правило.
Готовые CSS-анимации
Пять анимаций, которые закрывают почти все задачи интерфейса. Демо слева крутятся бесконечно, чтобы их было видно. В коде повтор стоит только там, где он нужен по смыслу.
Появление элемента
Самая частая анимация. Блок всплывает снизу и проявляется. fill-mode: both удерживает конечное состояние, иначе элемент мигнёт обратно.
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: none; }
}
.card {
animation: fadeInUp 0.5s ease both;
}Пульсация
Мягко привлекает внимание к кнопке или индикатору. Работает бесконечно, поэтому не ставьте её на важный текст.
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.08); opacity: 0.8; }
}
.badge {
animation: pulse 1.5s ease-in-out infinite;
}Загрузка, спиннер
Бесконечное вращение с линейной функцией времени. Любая другая даст рывок на стыке оборотов.
@keyframes spin {
to { transform: rotate(360deg); }
}
.loader {
animation: spin 0.8s linear infinite;
}Мерцание, скелетон
Заглушка на месте ещё не загруженного контента. Двигаем градиент, а не размеры, поэтому вёрстка не пересчитывается.
@keyframes shimmer {
from { background-position: -200% 0; }
to { background-position: 200% 0; }
}
.skeleton {
background: linear-gradient(
90deg,
#e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%
);
background-size: 200% 100%;
animation: shimmer 1.4s linear infinite;
}Встряска при ошибке
Короткое движение по горизонтали, понятный сигнал о неверном пароле или незаполненном поле.
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-6px); }
40%, 80% { transform: translateX(6px); }
}
.input.error {
animation: shake 0.4s ease;
}Анимация кнопки при наведении
Для наведения @keyframes обычно не нужен, хватает transition. Она оживляет переход между обычным состоянием и :hover, и это дешевле. Наведите курсор на карточку ниже.
.card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}Тень для такой карточки удобно подобрать в генераторе теней.
animation или transition
Разница в том, кто запускает движение. Transition реагирует на событие: наведение, клик, добавление класса. Переходить он умеет только между двумя состояниями. Animation живёт сама, стартует без событий, проходит через любое число кадров и может повторяться бесконечно. Наведение и клик — transition; лоадер, пульсация, появление при загрузке страницы — animation.
Свойства анимации
| Свойство | Что делает |
|---|---|
animation-name | Имя правила @keyframes, которое нужно проиграть. |
animation-duration | Длительность одного цикла. Для интерфейса обычно 0.2–0.6s, дольше движение начинает раздражать. |
animation-timing-function | Кривая скорости. Бывает ease, linear, ease-in-out или своя cubic-bezier(). |
animation-delay | Задержка перед стартом. Разные задержки у соседних элементов дают эффект каскада. |
animation-iteration-count | Число повторов. Значение infinite крутит анимацию бесконечно. |
animation-direction | Направление. Значение alternate проигрывает каждый второй цикл задом наперёд, движение идёт туда-обратно без рывка. |
animation-fill-mode | Что показывать до и после анимации. Значение both оставляет элемент в конечном кадре. |
Всё это записывается одной строкой: animation: pulse 1.5s ease-in-out 0s infinite alternate both. Свою кривую скорости можно собрать в генераторе cubic-bezier.
Почему анимация дёргается
Почти всегда причина одна: анимируются свойства, которые меняют вёрстку. width, height, margin, top и left заставляют браузер пересчитывать раскладку страницы на каждом кадре. А transform и opacity считаются на видеокарте и вёрстку не трогают. Поэтому сдвиг делайте через transform: translate(), а увеличение через transform: scale(), а не изменением размеров.
И не забудьте про тех, кому движение мешает физически. Часть людей отключает анимации в настройках системы. Уважить эту настройку можно одним медиазапросом.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}Больше приёмов и разбор нетривиальных случаев собраны в подробном гайде по CSS-анимациям.
Похожие инструменты
Другие полезные инструменты из той же категории
Часто задаваемые вопросы
Нужны две вещи. Сначала описываете кадры в правиле @keyframes: что происходит в начале (0% или from) и в конце (100% или to). Затем подключаете их к элементу свойством animation, указав имя и длительность: animation: fadeIn 0.5s ease. Всё остальное — задержку, повторы, направление — добавляете при необходимости. Конструктор выше собирает такой код сам.
Transition оживляет переход между двумя состояниями и запускается только по событию — например, при наведении. Animation умеет больше: она проигрывается сама, может иметь сколько угодно промежуточных кадров и повторяться бесконечно. Правило простое: наведение и клик — transition, самостоятельное движение вроде лоадера или пульсации — animation.
Классический fade-in: @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }, а затем animation: fadeIn 0.4s ease both. Ключевое слово both в fill-mode оставляет элемент в конечном состоянии, иначе он мигнёт обратно.
Для наведения обычно хватает transition — она дешевле и не требует @keyframes: .btn { transition: transform .2s ease, box-shadow .2s ease; } .btn:hover { transform: translateY(-2px); }. Если нужен непрерывный эффект (пульсация, мерцание), тогда уже подключайте animation с infinite.
Добавьте значение infinite в свойство animation: animation: pulse 1.5s ease-in-out infinite. Так делают лоадеры, пульсирующие точки и мигающие индикаторы. Чтобы движение шло туда-обратно без рывка на стыке, добавьте alternate — анимация будет проигрываться в обратную сторону через раз.
Плавно и дёшево анимируются transform и opacity — их браузер считает на видеокарте, не пересобирая вёрстку. А вот width, height, margin, top и left заставляют пересчитывать раскладку на каждом кадре, и на слабых устройствах анимация начинает дёргаться. Сдвиг делайте через transform: translate(), а не через left.
Плавность задаёт функция времени. Linear даёт механическое равномерное движение, ease-in-out — естественный разгон и торможение. Если нужна своя кривая, подберите её в генераторе cubic-bezier и подставьте в animation-timing-function.
Часть людей отключает анимации в системе из-за укачивания. Уважайте эту настройку через медиазапрос: @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; } }. Это требование доступности, и его легко забыть.