CSS-анимации: большой разбор

CSS-анимации: большой разбор

Заглядываем внутрь веб-красоты

В наших веб-проектах мы часто используем CSS-анимации — они позволяют без JavaScript придавать элементам страницы интерактивность. Сегодня разберём, по какому принципу работают анимации в CSS, какие есть основные свойства и где брать интересные элементы для своих проектов.

Введение в CSS-анимации

Анимации в веб-дизайне — это не просто эффектный элемент, на самом деле они выполняют важные задачи. С их помощью можно привлечь внимание пользователей к ключевым деталям интерфейса и улучшить пользовательский опыт.

Анимации делают интерфейс более понятным, показывая, что происходит: загрузка данных, переход между страницами или результат действия. К тому же аккуратные и плавные движения создают ощущение продуманного и современного дизайна. Интерфейс становится не только визуально приятным, но и функциональным.

В CSS анимации реализуются без использования JavaScript и работают благодаря двум возможностям:

  1. Правило @keyframes, которое определяет ключевые кадры анимации и задаёт, как элемент будет двигаться или изменяться.
  2. Свойство animation, которое применяется к элементу и отвечает за управление анимацией — её продолжительность, задержку, направление и другие параметры.

Получается, что сначала мы описываем набор правил для анимации, а затем подключаем её к элементу. В комбинации эти возможности позволяют создавать сложные эффекты — от простого мигания текста до имитации физических движений.

Теперь подробно рассмотрим, как это работает.

Правило @keyframes

CSS-анимации строятся на основе правила @keyframes, которое позволяет задать ключевые кадры (состояния) анимации. С помощью @keyframes мы описываем, как изменяется внешний вид элемента на протяжении всей анимации.

Но сам по себе @keyframes — это просто набор инструкций. Чтобы анимация начала работать, её нужно подключить к элементу с помощью свойства animation. Оно связывает элемент с конкретной анимацией, задаёт её продолжительность, задержку, направление и другие параметры.

Синтаксис @keyframes простой:

@keyframes имя_анимации {
  from { /* начальное состояние */ }
  to { /* конечное состояние */ }
}

Если нужно больше контроля, можно задавать промежуточные состояния в процентах:

@keyframes имя_анимации {
  0% { /* начальное состояние */ }
  50% { /* состояние в середине */ }
  100% { /* конечное состояние */ }
}

Суть анимации — в постепенном переходе от одного набора CSS-стилей к другому. В процессе анимации можно изменять набор стилей несколько раз, задавая промежуточные состояния для создания сложных и динамичных эффектов. Мы можем анимировать следующие CSS-свойства:

  • Позиционирование — transform, top, left, right, bottom.
  • Цвета — color, background-color, border-color.
  • Размеры — width, height, padding, margin.
  • Прозрачность — opacity.
  • Тени — box-shadow, text-shadow.
  • Контуры — border-width, border-radius.

Примеры использования @keyframes

Правило @keyframes используют для создания различных эффектов — движения, затемнения, вращения и так далее. Рассмотрим пару примеров:

/* Изменение прозрачности элемента */
@keyframes fadeIn {
  from {
    opacity: 0; /* Начальная прозрачность */
  }
  to {
    opacity: 1; /* Полностью видимый */
  }
}
CSS-анимации: большой разбор
/* Изменение цвета элемента */
@keyframes colorChange {
  0% {
/* Красный цвет */
    background-color: red; 
  }
  50% {
/* Жёлтый цвет */
    background-color: yellow; 
  }
  100% {
/* Зелёный цвет */
    background-color: green; 
  }
}
CSS-анимации: большой разбор

Дальше, чтобы эти анимации заработали, их нужно подключить к элементу через свойство animation.

Свойство animation

Свойство animation отвечает за то, как анимации применяются к элементу. С его помощью можно задать, что именно будет происходить, сколько это займёт времени, как часто станет повторяться и с какой скоростью. Анимацию можно настроить с помощью отдельных свойств или указать всё сразу в сокращённой форме.

animation-name

Это имя нашей анимации, которая прописана в @keyframes. Без него ничего работать не будет — именно так CSS понимает, какую анимацию нужно запустить.

/* Определяем анимацию затухания */
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
.element {
/* Применяем анимацию через animation-name */
  animation-name: fadeIn;
/* Указываем длительность, чтобы анимация заработала */
  animation-duration: 2s; 
}
CSS-анимации: большой разбор

animation-duration

Свойство animation-duration задаёт, сколько времени займёт выполнение одного цикла анимации. Значение указывается в секундах (s) или миллисекундах (ms). Например:

/* анимация выполняется за 2 секунды */
 animation-duration: 2s;

Если animation-duration не задано, анимация не будет видна, так как её выполнение займёт 0 секунд.

animation-timing-function

Свойство animation-timing-function определяет кривую скорости анимации, то есть то, как она изменяет CSS-стили в течение времени. Кривая скорости задаёт, сколько времени потребуется для перехода от одного набора стилей к другому на каждом этапе анимации. Свойство помогает сделать переходы более плавными и естественными, избегая резких изменений.

Например:

  • С ease-in анимация начинается медленно, затем ускоряется.
  • С ease-out анимация быстро стартует и замедляется к концу.

Все эти значения основаны на кривых Безье (Cubic Bezier). Это математический способ описания кривой скорости анимации. Есть даже интерактивный сайт, где можно настраивать кривую Безье, изменяя точки на графике, и сразу видеть, как изменяется анимация.

CSS-анимации: большой разбор

animation-iteration-count

Свойство animation-iteration-count определяет, сколько раз должна воспроизводиться анимация. Значением у animation-iteration-count может быть либо число, либо infinite:

  • число указывает точное количество повторений;
  • infinite задаёт бесконечное воспроизведение анимации.
.element {
/* Анимация выполнится два раза */
  animation-iteration-count: 2;
}
.element {
/* Анимация будет повторяться бесконечно */
  animation-iteration-count: infinite; 
}

animation-direction

Свойство animation-direction задаёт направление воспроизведения анимации: вперёд, назад или чередуя направления. Возможных значений у свойства может быть много:

animation-direction: normal|reverse|alternate|alternate-reverse|initial|inherit;

Разберёмся на примере. Допустим, у нас есть анимация перемещения прямоугольника div. Он горизонтально сдвигается на 100 пикселей:

@keyframes slide {
 from {
   /* Начальная позиция */
   transform: translateX(0);
 }
 to {
   /* Конечная позиция */
   transform: translateX(100px);
 }
}

С помощью animation-direction мы можем задать разные направления движения для разных прямоугольников:

/* анимация движется только вперёд (от начального кадра к конечному) */
.normal {
 /* Синий цвет */
 background-color: #3498db;
 /* Имя анимации */
 animation-name: slide;
 /* Длительность одного цикла — 2 секунды */
 animation-duration: 2s;
 /* Анимация повторяется бесконечно */
 animation-iteration-count: infinite;
 /* Движение только вперёд */
 animation-direction: normal;
}
/* анимация движется в обратном направлении (от конечного кадра к начальному) */
.reverse {
 /* Красный цвет */
 background-color: #e74c3c;
 animation-name: slide;
 animation-duration: 2s;
 animation-iteration-count: infinite;
 /* Движение назад */
 animation-direction: reverse;
}
/* направление чередуется (сначала вперёд, затем назад) */
.alternate {
 /* Зелёный цвет */
 background-color: #2ecc71;
 animation-name: slide;
 animation-duration: 2s;
 animation-iteration-count: infinite;
 /* Сначала вперёд, затем назад */
 animation-direction: alternate;
}
/* направление чередуется, начиная с обратного (сначала назад, затем вперёд) */
.alternate-reverse {
 /* Жёлтый цвет */
 background-color: #f1c40f;
 animation-name: slide;
 animation-duration: 2s;
 animation-iteration-count: infinite;
 /* Сначала назад, затем вперёд */
 animation-direction: alternate-reverse;
}

На странице это будет выглядеть так:

CSS-анимации: большой разбор

Если мы пропишем значение initial, то будет установлено значение по умолчанию (normal).

Значение inherit наследует значение от родительского элемента.

animation-delay

Свойство animation-delay задаёт задержку перед началом анимации. Мы можем явно указать, через какое время после применения стилей анимация начнёт воспроизводиться. Значение указывается в секундах или миллисекундах.

.element {
 /* Задержка перед началом анимации — 2 секунды */
   animation-delay: 2s;
}

animation-play-state

Свойство animation-play-state определяет, находится ли анимация в состоянии воспроизведения или паузы. Это позволяет управлять анимацией, останавливая её в нужный момент или возобновляя выполнение. Это особенно полезно при использовании JavaScript, чтобы останавливать или запускать анимацию динамически, например по событию нажатия кнопки или наведению мыши.

Когда анимация находится на паузе, она «запоминает» текущую позицию и продолжает воспроизведение с того же момента после снятия паузы.

Можно прописать одно из двух значений:

  • running — воспроизводится (по умолчанию);
  • paused — приостанавливается, в этом состоянии элемент остаётся в текущем кадре анимации.

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

@keyframes move {
 from {
   transform: translateX(0);
 }
 to {
   transform: translateX(200px);
 }
}

Теперь применим её к кнопке и зададим animation-play-state — running. То есть при загрузке страницы анимация срабатывает:

button {
 /* остальные стили кнопки опущены для краткости */
 /* Имя анимации */
 animation-name: move;  
/* Длительность анимации */
 animation-duration: 3s;  
/* Бесконечное повторение */
animation-iteration-count: infinite;  
/* Анимация воспроизводится по умолчанию */
animation-play-state: running; 
}

Анимация работает, кнопка по умолчанию движется, но при наведении курсора пока ничего не происходит:

CSS-анимации: большой разбор

Теперь зададим кнопке псевдокласс hover и пропишем в нём остановку анимации:

/* При наведении ставим анимацию на паузу */
button:hover {
 /* Анимация приостанавливается */
 animation-play-state: paused;
}

Теперь при наведении курсора движение кнопки останавливается:

CSS-анимации: большой разбор

А если нужно сделать что-то ещё более сложное, например останавливать анимации на определённом этапе, возобновлять анимацию по таймеру или по другим условиям, то здесь в дополнение уже понадобится JavaScript.

animation-fill-mode

Свойство animation-fill-mode определяет, как элемент выглядит до начала анимации и после её завершения. Обычно анимация влияет на элемент только во время своего выполнения: до старта он выглядит как обычно, а после окончания возвращается в исходное состояние. Но с помощью animation-fill-mode можно изменить это поведение, чтобы элемент запоминал своё начальное или конечное состояние. Например, можно сделать так, чтобы он сразу выглядел, как в начале анимации, или сохранял стиль после её завершения.

У этого свойства есть четыре параметра:

  • None (значение по умолчанию). Анимация влияет на элемент только во время своего выполнения. До начала и после завершения анимации элемент возвращается к своим исходным стилям.
  • Forwards. После завершения анимации элемент остаётся в том состоянии, которое задано в последнем ключевом кадре.
  • Backwards. До начала анимации, включая время задержки, элемент принимает стили из первого ключевого кадра. Это нужно, чтобы избежать резких изменений, пока анимация ещё не началась.
  • Both. Элемент сразу принимает стили первого ключевого кадра до начала анимации и сохраняет стили последнего кадра после её завершения. Это объединяет поведение значений forwards и backwards.

Посмотрим на примере. Допустим, у нас есть анимированный блок, который меняется в размерах и цветах — из синего становится зелёным. Мы хотим, чтобы по завершении анимации он оставался в последнем трансформированном состоянии:

Задаем ключевые кадры анимации:

@keyframes resizeAndColor {
 0% {
   /* Начальная ширина */
   width: 100px;
   /* Начальная высота */
   height: 100px;
   /* Начальный цвет */
   background-color: #683eef;
 }
 100% {
   /* Конечная ширина */
   width: 200px;
   /* Конечная высота */
   height: 200px;
   /* Конечный цвет */
   background-color: #d6fb51;
 }
}

Теперь прописываем стили для нашего блока и подключаем к нему анимацию:

.block {
 /* Начальная ширина */
 width: 100px;
 /* Начальная высота */
 height: 100px;
 /* Начальный цвет */
 background-color: #683eef;
 /* Имя анимации */
 animation-name: resizeAndColor;
 /* Длительность анимации */
 animation-duration: 3s;
 /* Сохраняем конечное состояние */
 animation-fill-mode: forwards;
}

Вот что получилось:

CSS-анимации: большой разбор

Блок при загрузке страницы меняет цвет, увеличивается и остаётся в новом состоянии по завершении анимации. А если мы пропишем вместо forwards значение backwards, то блок возвратится в состояние первого ключевого кадра, то есть станет маленьким и синим.

Краткая запись анимации

Значения в свойстве animation можно объединить в одну строку: имя, длительность, тайминг-функцию, задержку, количество повторений, направление, поведение до и после выполнения. В краткой записи свойства animation можно указать все значения, но в определённом порядке. Если мы не указываем какое-то значение, используется его значение по умолчанию:

/* @keyframes duration | easing-function | delay | iteration-count | direction | fill-mode | play-state | name */
animation: 3s ease-in 1s 2 reverse both paused slide-in;

В этой записи мы прописали длительность анимации, тайминг-функцию, задержку, количество повторений, направление, режим заполнения, состояние воспроизведения и имя анимации.

Применение нескольких анимаций

Можно назначить одному элементу сразу несколько анимаций, указав их через запятую в свойстве animation. Это позволяет комбинировать эффекты с разными таймингами, длительностью, направлениями и так далее.

Сделаем красивую вращающуюся анимацию. Возьмём элемент и заставим его плавно вращаться сначала в одну сторону, потом в другую, а затем добавить бесконечное чередование движений. Мы используем несколько ключевых кадров и объединим их в одну сложную анимацию.

Сначала сделаем базовую HTML-разметку и добавим элемент, который хотим анимировать:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Анимация</title>
  <!-- Подключаем файл стилей -->
  <link rel="stylesheet" href="animation.css">
</head>
<body>
  <!-- Элемент, который будет вращаться -->
 <img src="https://thecode.media/wp-content/themes/thecode_refresh/assets/svg/logo.svg" class="element"></img>
</body>
</html>

Теперь в файле со стилями пропишем стили для элемента:

/* Стили для элемента */
.element {
/* Задаём ширину элемента */
  width: 136px; 
}

Пока что у нас получился просто логотип на белом фоне:

CSS-анимации: большой разбор

Начнём анимировать его. Зададим для него три отдельные анимации (spin1, spin2, spin3). Каждая из них отвечает за свой этап движения:

  1. spin1 — вращение элемента на 180°;
  2. spin2 — продолжение вращения до 360°;
  3. spin3 — вращение на 360° в обратную сторону с чередованием.
/* Первая анимация: вращение на 180° */
@keyframes spin1 {
  from {
/* Начальная позиция */
    transform: rotate(0deg); 
  }
  to {
/* Вращение на 180° */
    transform: rotate(180deg); 
  }
}
/* Вторая анимация: вращение на оставшиеся 180° */
@keyframes spin2 {
  from {
 /* Продолжение со 180° */
    transform: rotate(180deg);
  }
  to {
/* Завершение полного круга */
    transform: rotate(360deg); 
  }
}
/* Третья анимация: вращение в обратную сторону */
@keyframes spin3 {
  from {
/* Начальная позиция */
    transform: rotate(0deg); 
  }
  to {
/* Вращение на 360° в противоположную сторону */
    transform: rotate(-360deg); 
  }
}

Мы прописали правила для трёх анимаций, но пока ничего не происходит — сами анимации ещё не подключены к элементу. Для этого мы используем свойство animation, которое связывает элемент с нашими анимациями.

Также в этом свойстве мы указываем скорость выполнения каждой анимации (время), тайминг-функцию и дополнительные параметры — задержку (delay) и бесконечное повторение (infinite).

Добавим всё это к элементу, чтобы анимации начали работать:

.element {
 width: 136px;
   /* Подключение трёх анимаций */
  animation: 
    spin1 1s linear, /* Первая анимация: вращение на 180° за 1 секунду с линейной скоростью */
    spin2 2s ease 1.5s, /* Вторая анимация: вращение до 360° за 2 секунды, начинается с задержкой 1,5 секунды */
    spin3 5s ease-in-out 4s infinite alternate; /* Третья анимация: вращение в обратную сторону на 360° с чередованием, бесконечно */
}

Смотрим, что получилось:

CSS-анимации: большой разбор

Примеры CSS-анимаций

Для создания движения часто используют свойство transform, которое поддерживает функции translate, rotate, scale и их комбинации. Это позволяет создавать разные красивые штуки: вращающиеся спиннеры, пульсирующие индикаторы и сложные переходы между формами.

Пример анимации с дополнительным JS:

CSS-анимации: большой разбор

В веб-проекте «Делаем аквариум с разными обитателями» мы использовали анимацию для движения рыбок. С помощью свойства transform рыбки плывут из одной стороны аквариума в другую, затем разворачиваются, используя scaleX, и возвращаются обратно.

https://thecode.media/wp-content/uploads/2024/01/aquarium-1.gif

В веб-проекте «Делаем браузерную игру с динозавриком, как в Chrome», мы реализовали прыжки динозаврика с помощью свойства top. Каждый ключевой кадр определял положение динозаврика на определённой стадии прыжка: от начальной позиции до самой высокой точки и обратно.

https://thecode.media/wp-content/uploads/2024/05/unnamed.gif

Доступность анимаций

Не все пользователи любят или могут воспринимать активные анимации. Например, кому-то комфортно смотреть на сложные движения или мерцания на экране. Некоторые анимации даже могут вызывать дискомфорт или ухудшать восприятие контента. Поэтому важно делать их доступными для всех.

Благодаря медиазапросу prefers-reduced-motion можно уменьшить или отключить анимации для тех, кто предпочитает минимальное движение.

Современные браузеры поддерживают настройку prefers-reduced-motion. Это системный параметр, который пользователи включают, чтобы уменьшить или отключить анимации. С помощью этого медиазапроса можно адаптировать сайт:

/* Убираем анимацию для пользователей с prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .element {
/* Отключаем анимацию */
    animation: none; 
  }
}

Если пользователь включил настройку «уменьшить движения» (Reduce Motion) в своей системе, анимация автоматически отключится. Это простой способ позаботиться о пользователе и сделать UX сайта лучше.

CSS-анимации: большой разбор

Кроме того, вспышки и быстро меняющиеся кадры могут вызвать дискомфорт у пользователей с повышенной чувствительностью. Поэтому важно использовать плавные переходы — ease-in-out и прочие.

Поддержка браузерами

Современные браузеры хорошо поддерживают большинство возможностей CSS-анимаций — @keyframes, сокращённую запись animation и медиазапросы prefers-reduced-motion.

В старых версиях Internet Explorer (до IE 11) и некоторых устаревших браузерах поддержка анимаций отсутствует или ограничена. Если важна обратная совместимость, используйте полифилы, то есть дополнительные библиотеки или скрипты, которые добавляют поддержку функциональности CSS-анимаций в браузерах.

CSS-анимации: большой разбор

Dev Tools в браузерах позволяют эмулировать настройки, например prefers-reduced-motion, и тестировать поведение анимаций во вкладке «Анимации».

CSS-анимации: большой разбор

Полезные ресурсы и библиотеки

Чтобы упростить создание анимаций и вдохновиться интересными эффектами, можно использовать готовые ресурсы и инструменты — библиотеки и генераторы для анимаций:

  • Animista — интерактивный генератор анимаций с большим выбором эффектов. Выберите нужный эффект, настройте параметры и получите готовый CSS-код.
  • Keyframes — инструмент для создания и настройки анимаций прямо в браузере. Позволяет визуально редактировать ключевые кадры.
  • Animate.css — популярная библиотека с готовыми эффектами. Подключите её и добавьте классы для быстрого использования анимаций.
  • Hover.css — коллекция эффектов наведения для кнопок, ссылок и других элементов.
  • GSAP (GreenSock) — инструмент для сложных и кроссбраузерных анимаций. Работает с CSS, SVG и JavaScript.
Вам может быть интересно
easy

Обложка:

Алексей Сухов

Корректор:

Елена Грицун

Вёрстка:

Кирилл Климентьев

Соцсети:

Юлия Зубарева