CSS анимации - css-animations от базовых примеров до продвинутых техник

05 марта 2026
Автор

Олег Марков

Введение

CSS анимации позволяют «оживлять» интерфейс без JavaScript. Вы можете плавно изменять положение элементов, их размер, цвет, прозрачность и десятки других свойств. Главное преимущество в том, что браузер сам управляет анимацией и может оптимизировать ее под устройство пользователя.

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

Что такое CSS анимации и чем они отличаются от transition

Переходы (transition) против анимаций (animation)

Для начала давайте разведем два похожих механизма:

  • transition — анимация запускается при изменении состояния (например, при :hover, :focus, добавлении класса).
  • animation — анимация может идти сама по себе, по циклу, запускаться при загрузке страницы и не требует смены состояния.

Коротко различия в поведении:

  • transition:

    • Нужны исходное и конечное состояние.
    • Запускается при изменении CSS-свойства.
    • Обычный сценарий — плавный переход по наведению.
  • animation:

    • Набор промежуточных состояний в @keyframes.
    • Может запускаться автоматически при загрузке.
    • Может быть бесконечной, обратимой, управляемой задержкой и направлением.

Смотрите, я покажу вам маленькое сравнение.

Пример с transition

.button {
  background-color: #3498db;
  transition: background-color 0.3s ease; /* Плавное изменение цвета */
}

.button:hover {
  background-color: #2ecc71; /* При наведении меняем цвет */
}
<button class="button">Наведи на меня</button>

Здесь анимация есть, но вы ее не описываете отдельно. Браузер автоматически интерполирует цвет от синего к зеленому при наведении и обратно при уходе курсора.

Пример с animation

@keyframes pulse {
  0% {
    transform: scale(1);   /* Начальный размер */
  }
  50% {
    transform: scale(1.1); /* Увеличение */
  }
  100% {
    transform: scale(1);   /* Возврат к исходному размеру */
  }
}

.button-pulse {
  animation-name: pulse;      /* Имя анимации */
  animation-duration: 1s;     /* Длительность одного цикла */
  animation-iteration-count: infinite; /* Бесконечное повторение */
}
<button class="button-pulse">Я пульсирую</button>

Как видите, здесь вы явно задаете все ключевые состояния. Запуск происходит сам по себе — ничего не нужно «триггерить» через hover.

Основы CSS анимаций: @keyframes и базовые свойства

Объявление ключевых кадров с @keyframes

В основе CSS анимаций лежит правило @keyframes. В нем вы описываете, как будут меняться свойства элемента на протяжении анимации.

Общий вид:

@keyframes имяАнимации {
  0% {
    /* Начальное состояние */
  }
  50% {
    /* Промежуточное состояние */
  }
  100% {
    /* Конечное состояние */
  }
}
  • Имя анимации — произвольное (латиница, цифры, дефисы), например fade-in, slideUp, spin.
  • Вы можете использовать проценты (0%, 25%, 50%, 100%) или ключевые слова from и to:
    • from = 0%
    • to = 100%

Давайте разберемся на простом примере появления блока с постепенным увеличением непрозрачности.

/* Объявляем анимацию плавного появления */
@keyframes fade-in {
  from {
    opacity: 0;   /* Невидим в начале */
  }
  to {
    opacity: 1;   /* Полностью видим в конце */
  }
}

/* Применяем к элементу */
.box {
  opacity: 0;                /* Стартовое состояние для гарантии */
  animation-name: fade-in;   /* Указываем, какую анимацию применить */
  animation-duration: 1s;    /* Длительность анимации */
  animation-fill-mode: forwards; /* Сохраняем конечное состояние */
}
<div class="box">Я появлюсь плавно</div>

Комментарии в коде помогают вам увидеть, какие свойства за что отвечают. Мы еще вернемся к animation-fill-mode, потому что это важный момент.

Свойства семейства animation

Свойств в группе animation-* довольно много. Сейчас посмотрим главное, а дальше пойдем глубже.

Основные:

  • animation-name — имя анимации (@keyframes), которую вы хотите использовать.
  • animation-duration — длительность одного цикла (например 1s, 500ms).
  • animation-timing-function — функция временного распределения (например ease, linear, ease-in-out).
  • animation-delay — задержка перед стартом анимации.
  • animation-iteration-count — количество повторений (1, 3, infinite).
  • animation-direction — направление (normal, reverse, alternate, alternate-reverse).
  • animation-fill-mode — что происходит с элементом до и после анимации.
  • animation-play-state — статус воспроизведения (running или paused).

И есть сокращенное свойство animation, которое позволяет задать все сразу. Чуть позже я покажу вам удобный способ пользоваться шорткатом.

Подробный разбор @keyframes

Использование нескольких ключевых точек

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

@keyframes move-and-fade {
  0% {
    transform: translateX(0);    /* Стартовая позиция */
    opacity: 0;                  /* Невидим */
  }
  25% {
    transform: translateX(50px); /* Сместился немного */
    opacity: 0.5;                /* Полупрозрачен */
  }
  50% {
    transform: translateX(100px);/* Сместился дальше */
    opacity: 1;                  /* Полностью видим */
  }
  100% {
    transform: translateX(0);    /* Вернулся на место */
    opacity: 1;                  /* Все еще видим */
  }
}

.element {
  animation: move-and-fade 2s ease-in-out forwards;
}

Как видите, этот код выполняет одновременно два эффекта: элемент передвигается по оси X и меняет прозрачность. Между этими точками браузер сам «дорисовывает» промежуточные состояния.

Несколько свойств в одних ключевых кадрах

Внутри блока @keyframes вы можете менять сразу несколько свойств:

@keyframes complex-example {
  0% {
    transform: translateY(0) scale(1); /* Начало */
    opacity: 0;
    background-color: #3498db;
  }
  50% {
    transform: translateY(-20px) scale(1.05); /* Подскочил и увеличился */
    opacity: 1;
    background-color: #9b59b6;
  }
  100% {
    transform: translateY(0) scale(1); /* Вернулся в исходное положение */
    opacity: 1;
    background-color: #2ecc71;
  }
}

.card {
  animation: complex-example 1.5s ease-out forwards;
}

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

Несколько анимаций на одном элементе

Один элемент может участвовать сразу в нескольких анимациях. Для этого значения свойств animation-* перечисляются через запятую.

Покажу вам, как это выглядит в коде.

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes slide-down {
  from {
    transform: translateY(-20px);
  }
  to {
    transform: translateY(0);
  }
}

.block {
  /* Две анимации применяются одновременно */
  animation-name: fade-in, slide-down;           /* Две анимации */
  animation-duration: 0.8s, 0.8s;                /* Длительность для каждой */
  animation-timing-function: ease-out, ease-out; /* Кривая для каждой */
  animation-fill-mode: forwards, forwards;       /* Обе сохраняют финальное состояние */
}

Здесь я размещаю пример с двумя анимациями, чтобы вам было проще понять принцип. Порядок значений должен соответствовать порядку имен.

Для сокращенного синтаксиса можно написать:

.block {
  animation:
    fade-in 0.8s ease-out forwards,
    slide-down 0.8s ease-out forwards;
}

Такая запись проще читается и часто используется в продакшне.

Свойства animation: детальный разбор

animation-duration

Отвечает за продолжительность одного полного цикла анимации.

.box {
  animation-name: fade-in;
  animation-duration: 2s;  /* Длительность 2 секунды */
}
  • Значения: s (секунды), ms (миллисекунды).
  • Не может быть отрицательным.
  • Если не указано, по умолчанию 0s — анимация не проиграется.

animation-timing-function

Управляет тем, как меняется скорость анимации во времени.

Основные значения:

  • linear — равномерная скорость.
  • ease — стандартная кривая браузера (ускорение, затем замедление).
  • ease-in — плавный старт, затем ускорение.
  • ease-out — быстрое начало, плавное завершение.
  • ease-in-out — плавный старт и плавное окончание.
  • steps(n, start|end) — ступенчатая анимация (без плавных переходов).

Давайте посмотрим на примере ступенчатой анимации, которая часто используется для «печатающего» текста.

@keyframes typing {
  from {
    width: 0;   /* Начинаем с нулевой ширины */
  }
  to {
    width: 20ch; /* Показываем 20 символов */
  }
}

.text-typing {
  overflow: hidden;                                 /* Скрываем лишний текст */
  white-space: nowrap;                              /* Запрещаем перенос строк */
  animation: typing 4s steps(20, end) forwards;     /* 20 «шагов» - по символу */
}
<p class="text-typing">
  Этот текст будет появляться как при печати.
</p>

Комментарии поясняют, что steps(20, end) будет обновлять ширину кусками, создавая эффект «символ за символом».

animation-delay

Задержка перед запуском анимации. Используется, чтобы создавать очередность.

.item {
  animation: fade-in 1s ease forwards;
}

.item:nth-child(1) {
  animation-delay: 0s;   /* Без задержки */
}

.item:nth-child(2) {
  animation-delay: 0.2s; /* Небольшая задержка */
}

.item:nth-child(3) {
  animation-delay: 0.4s; /* Еще больше задержка */
}

Такой прием часто используют для «каскадных» появлений элементов списка или карточек.

animation-iteration-count

Определяет, сколько раз повторится анимация.

  • Число (например 1, 3, 10).
  • infinite — бесконечный цикл.
.loader {
  animation: spin 1s linear infinite; /* Крутится постоянно */
}
@keyframes spin {
  to {
    transform: rotate(360deg); /* Поворот на полный круг */
  }
}

Здесь достаточно указать только to, потому что from по умолчанию считается текущим состоянием.

animation-direction

Отвечает за направление движения по ключевым кадрам.

Основные значения:

  • normal — проигрывание от 0% к 100%.
  • reverse — от 100% к 0%.
  • alternate — сначала вперед, затем назад, затем снова вперед (чередование).
  • alternate-reverse — сначала назад, затем вперед, и так по кругу.

Давайте разберемся с эффектом «маятника».

@keyframes move-left-right {
  0% {
    transform: translateX(0);     /* Центр */
  }
  100% {
    transform: translateX(50px);  /* Сдвиг вправо */
  }
}

.pendulum {
  animation: move-left-right 1s ease-in-out infinite alternate;
  /* alternate - туда и обратно */
}

Здесь анимация сначала идет к 100%, затем автоматически воспроизводится обратно к 0%, создавая туда-обратно движение без дополнительных ключевых кадров.

animation-fill-mode

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

Варианты:

  • none — анимация не влияет на стиль до начала и после окончания.
  • forwards — после завершения анимации элемент остается в состоянии последнего ключевого кадра.
  • backwards — до начала анимации (во время задержки) применяются стили из первого ключевого кадра.
  • both — объединяет forwards и backwards.

Посмотрим пример с задержкой.

@keyframes appear {
  from {
    opacity: 0;        /* Невидим в начале */
    transform: scale(0.5);
  }
  to {
    opacity: 1;        /* Видим в конце */
    transform: scale(1);
  }
}

/* Вариант без fill-mode */
.box-none {
  opacity: 0;                      /* Задаем вручную */
  animation: appear 1s ease 2s;    /* 2 секунды задержки */
}

/* Вариант с backwards */
.box-backwards {
  animation: appear 1s ease 2s backwards;
  /* В момент задержки сразу применяются стили from (opacity 0 scale 0.5) */
}
  • Без backwards элемент до начала анимации будет в том состоянии, которое задано обычными стилями (opacity: 0 в примере).
  • С backwards стили начального ключевого кадра применяются во время задержки, и вы можете не дублировать их в основном селекторе.

forwards полезен, когда вы хотите сохранить финальное состояние, например, сделать появление элемента один раз без отката назад.

animation-play-state

Позволяет ставить анимацию на паузу и продолжать.

.box {
  animation: move 3s linear infinite;
}

/* Класс для паузы */
.box.paused {
  animation-play-state: paused; /* Останавливаем анимацию */
}

Этот прием часто используют в сочетании с JavaScript, но сам факт — свойство чисто CSS-ное. С помощью скрипта вы просто добавляете или удаляете класс paused.

Сокращенное свойство animation

Все перечисленные параметры можно объединить в одно свойство animation. Это облегчает чтение стилей и уменьшает их объем.

Порядок значений:

  1. animation-name
  2. animation-duration
  3. animation-timing-function
  4. animation-delay
  5. animation-iteration-count
  6. animation-direction
  7. animation-fill-mode
  8. animation-play-state

Не все обязательно указывать — эти значения частично опциональны, но порядок должен соблюдаться.

Пример:

.box {
  animation: fade-in 1s ease-out 0.5s 3 alternate forwards running;
  /* имя    длит кривая задержка кол-во напр   fill     состояние */
}

На практике чаще ограничиваются 2–4 параметрами:

.box {
  animation: fade-in 1s ease-out forwards;
}

Этого уже достаточно для множества задач.

Практические примеры CSS анимаций

Теперь давайте посмотрим на практику. Ниже несколько типичных эффектов, которые вы можете использовать в интерфейсе.

Плавное появление модального окна

@keyframes modal-show {
  from {
    opacity: 0;
    transform: translateY(-20px); /* Сдвиг вверх */
  }
  to {
    opacity: 1;
    transform: translateY(0);     /* Исходное положение */
  }
}

.modal {
  opacity: 0;                         /* По умолчанию скрыто */
  transform: translateY(-20px);       /* Начальный сдвиг */
  animation: modal-show 0.4s ease-out forwards;
}
<div class="modal">
  Контент модального окна
</div>

Комментарии показывают, что мы в ключевых кадрах описали и прозрачность, и смещение. forwards гарантирует, что после завершения анимации окно останется в видимом состоянии.

Анимация «подсветки» кнопки по наведению

@keyframes button-highlight {
  0% {
    box-shadow: 0 0 0 rgba(46, 204, 113, 0);  /* Без тени */
  }
  50% {
    box-shadow: 0 0 15px rgba(46, 204, 113, 0.7); /* Сильное свечение */
  }
  100% {
    box-shadow: 0 0 0 rgba(46, 204, 113, 0);  /* Возврат к нулю */
  }
}

.button {
  background-color: #2ecc71;
  border: none;
  color: #fff;
  padding: 0.75rem 1.5rem;
  cursor: pointer;
}

.button:hover {
  animation: button-highlight 0.6s ease-out; /* Запускаем при наведении */
}

Эффект запускается только на время наведения, так как анимация связана с состоянием :hover.

Анимированная иконка «бургер-меню»

Смотрите, я покажу вам типичный пример, который часто встречается в реальных проектах.

.menu-icon {
  width: 30px;
  height: 20px;
  position: relative;
  cursor: pointer;
}

/* Общий стиль полосок */
.menu-icon span {
  position: absolute;
  left: 0;
  right: 0;
  height: 3px;
  background: #333;
  transition: transform 0.3s ease, top 0.3s ease, opacity 0.3s ease;
  /* Используем transition для простоты */
}

/* Верхняя полоска */
.menu-icon span:nth-child(1) {
  top: 0;
}

/* Средняя полоска */
.menu-icon span:nth-child(2) {
  top: 50%;
  transform: translateY(-50%);
}

/* Нижняя полоска */
.menu-icon span:nth-child(3) {
  bottom: 0;
}

/* Состояние "открыто" */
.menu-icon.open span:nth-child(1) {
  top: 50%;                           /* Смещаем к центру */
  transform: translateY(-50%) rotate(45deg); /* Поворачиваем */
}

.menu-icon.open span:nth-child(2) {
  opacity: 0;                         /* Прячем среднюю */
}

.menu-icon.open span:nth-child(3) {
  bottom: auto;
  top: 50%;                           /* Смещаем к центру */
  transform: translateY(-50%) rotate(-45deg); /* Поворачиваем */
}
<div class="menu-icon">
  <span></span>
  <span></span>
  <span></span>
</div>
// Пример простого JS - добавляем и убираем класс open по клику
document.querySelector('.menu-icon').addEventListener('click', function () {
  // Переключаем класс open при каждом клике
  this.classList.toggle('open');
});

Хотя здесь основное поведение реализовано с помощью transition, вполне возможно реализовать подобное поведение и через animation, если вам нужна более сложная последовательность шагов. Пример показывает, как анимации и переходы дополняют друг друга.

Прелоадер с вращающимся кругом

@keyframes loader-rotate {
  to {
    transform: rotate(360deg); /* Полный оборот */
  }
}

.loader {
  width: 40px;
  height: 40px;
  border: 4px solid #eee;            /* Светлый круг */
  border-top-color: #3498db;         /* Верхняя часть синяя */
  border-radius: 50%;
  animation: loader-rotate 0.8s linear infinite;
}
<div class="loader"></div>

Этот эффект почти не требует ресурсов, так как основной стиль анимации завязан на transform, который хорошо оптимизируется браузерами.

Анимации и производительность

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

Старайтесь анимировать только transform и opacity

Причина в том, что изменения многих CSS-свойств заставляют браузер:

  1. Пересчитывать раскладку (layout).
  2. Перерисовывать (paint) элемент.
  3. Собирать слои и выполнять композицию (composite).

transform и opacity обычно затрагивают только этап композиции. Это самый дешевый этап рендера, который лучше всего оптимизируется и ускоряется GPU.

Примеры безопасных анимаций:

@keyframes safe-move {
  from {
    transform: translateX(0);   /* Позиция */
  }
  to {
    transform: translateX(100px);
  }
}

@keyframes safe-fade {
  from {
    opacity: 0;                 /* Прозрачность */
  }
  to {
    opacity: 1;
  }
}

Нежелательные для частых анимаций свойства:

  • width, height
  • margin, padding
  • top, left, right, bottom
  • box-shadow (особенно с большим размытием)
  • border-radius при больших значениях

Иногда вам все равно придется анимировать их, но тогда стоит делать это реже или короче по времени.

Использование will-change

Свойство will-change подсказывает браузеру, какие свойства скоро будут изменены, и он может заранее оптимизировать эти элементы.

.card {
  will-change: transform, opacity; /* Подсказываем браузеру о будущем изменении */
}

Используйте его:

  • Для элементов с длительными или частыми анимациями.
  • Для элементов, которые заранее известно, что будут анимированы (например, всплывающие блоки).

Не стоит ставить will-change «везде» — это может наоборот ухудшить производительность, потому что браузер будет держать лишние слои.

Предпочитайте CSS анимации вместо JS там, где возможно

CSS-анимации:

  • Позволяют браузеру самостоятельно управлять частотой кадров.
  • Могут быть вынесены на отдельный поток, не зависящий от главного JS-потока.
  • Лучше оптимизируются на уровне движка.

JavaScript-анимации нужны, когда:

  • Требуется сложная логика синхронизации с данными.
  • Нужно подстраиваться под пользовательский ввод в реальном времени.
  • Нужна тонкая ручная настройка каждого шага.

Обычно оптимальный подход — комбинировать: использовать CSS для чистой визуализации, а JS только для управления классами и состояниями.

Управление анимациями через классы и JS

Хотя статья о CSS, в реальных проектах почти всегда анимации запускаются и останавливаются с помощью JavaScript, который добавляет или убирает классы.

Запуск анимации по клику

@keyframes bounce {
  0% {
    transform: translateY(0);      /* Старт */
  }
  30% {
    transform: translateY(-20px);  /* Прыжок вверх */
  }
  100% {
    transform: translateY(0);      /* Возврат вниз */
  }
}

.box {
  width: 100px;
  height: 100px;
  background: #e67e22;
  cursor: pointer;
}

/* Класс, который добавляется при запуске */
.box.bouncing {
  animation: bounce 0.6s ease; /* Один прыжок */
}
<div class="box"></div>
// На каждый клик добавляем класс bouncing
const box = document.querySelector('.box');

box.addEventListener('click', function () {
  // Удаляем класс, чтобы анимация перезапустилась
  this.classList.remove('bouncing');
  // Принудительно перерассчитываем стиль
  void this.offsetWidth; // Трюк для перезапуска анимации
  // Снова добавляем класс
  this.classList.add('bouncing');
});

Комментарии внутри показывают, почему нужно временно удалить класс и перерасчитать стили. Без этого анимация не перезапускается на повторном клике, так как браузер считает, что ничего не изменилось.

Остановка анимации

Если вам нужно полностью отключить анимацию, вы можете переопределить ее:

.box {
  animation: spin 2s linear infinite;
}

/* Класс для отключения */
.box.no-animation {
  animation: none; /* Полностью убираем анимацию */
}
// Пример переключения состояния
box.classList.add('no-animation');   // Отключить
box.classList.remove('no-animation'); // Включить

Этот подход полезен, если нужно, например, отключить «фановые» анимации по желанию пользователя.

Доступность и настройки пользователя (prefers-reduced-motion)

Не все пользователи хорошо переносят анимации. У некоторых они вызывают дискомфорт. Операционные системы позволяют указывать настройку «уменьшить движение», и вы можете ее учитывать.

Использование медиазапроса prefers-reduced-motion

@keyframes float {
  0% {
    transform: translateY(0);       /* Старт */
  }
  50% {
    transform: translateY(-10px);   /* Подъем */
  }
  100% {
    transform: translateY(0);       /* Возврат */
  }
}

.floating-element {
  animation: float 3s ease-in-out infinite;
}

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

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

@media (prefers-reduced-motion: reduce) {
  .floating-element {
    animation: float 1s ease-in-out 1;
  }
}

Так эффект сохранится, но будет менее навязчивым.

Отладка и типичные ошибки

Анимация не запускается

Проверьте:

  1. Указано ли animation-duration (по умолчанию 0s).
  2. Совпадает ли animation-name с именем @keyframes.
  3. Не стоит ли animation-play-state: paused.
  4. Не перекрывается ли анимация другим правилом (например, более специфичным селектором).
  5. Не забыли ли вы добавить нужный класс на элемент.

Пример проблемы с неправильным именем:

@keyframes fadeIn {  /* Здесь с заглавной буквы */
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.box {
  animation-name: fade-in;  /* Здесь с дефисом - другое имя */
  animation-duration: 1s;
}

В этом случае анимация вообще не запустится, потому что имена не совпадают. Исправьте на единый вариант.

Анимация перезапускается каждый раз при изменении класса

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

Конфликты с transition

Если одновременно на одно и то же свойство действуют и transition, и animation, поведение может стать непредсказуемым. Обычно стоит решать:

  • Одно свойство — только transition или только animation, не оба сразу;
  • Или стройте логику так, чтобы эффекты не пересекались по времени.

Например, анимировать позицию с помощью animation, а цвет — через transition.

Заключение

CSS анимации дают вам мощный инструмент для создания живых интерфейсов без сложного JavaScript-кода. Вы можете описывать последовательности состояний через @keyframes, управлять длительностью, повторением, задержкой, направлением и финальным состоянием элементов. Используя набор свойств animation-*, вы получаете тонкий контроль над всем жизненным циклом анимации.

Важно помнить о производительности и выбирать преимущественно анимацию transform и opacity, а также учитывать настройку prefers-reduced-motion, чтобы интерфейс оставался комфортным для всех пользователей. На практике CSS-анимации почти всегда используются в связке с классами и иногда с JS, который только переключает состояния.

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

Частозадаваемые технические вопросы

Как запустить анимацию только один раз при первом появлении элемента и не повторять при последующих рендерах

Сделайте анимационный класс одноразовым. Например, при первом монтировании элемента добавьте класс animated-once, а после события animationend удалите из DOM сам элемент анимационной обертки или замените класс на «статический». В чистом CSS можно имитировать это через комбинацию animation-fill-mode: forwards и отсутствие изменений состояния (не переключать классы и не трогать DOM), чтобы анимация не перезапускалась.

Как перезапустить CSS анимацию без JavaScript только средствами CSS

Без JS напрямую перезапустить анимацию нельзя, но можно использовать разные состояния, например :hover, :focus, :checked у скрытого чекбокса или :target. Выносите анимацию в отдельный класс, который привязан к одному из этих состояний, и при каждом новом срабатывании состояния анимация будет стартовать заново. Типичный прием — скрытый чекбокс и :checked как триггер.

Как сделать, чтобы анимация начиналась не сразу после загрузки страницы, а только когда элемент появится в области видимости

В чистом CSS надежно это сделать нельзя, нужен JavaScript. Используйте Intersection Observer, чтобы отслеживать, когда элемент попадает в viewport, и тогда добавляйте класс, который задает animation. Алгоритм такой — наблюдаете за элементом, при isIntersecting true добавляете класс animate-in, прописываете для него нужную анимацию, а при необходимости отписываетесь от наблюдения, чтобы не запускать анимацию повторно.

Как синхронизировать несколько анимаций на разных элементах так, чтобы они начинались и заканчивались одновременно

Используйте одинаковые animation-duration и animation-delay для всех элементов, а также одинаковые значения animation-timing-function. Если анимации должны быть разными по ключевым кадрам, создайте несколько @keyframes, но следите, чтобы их временная шкала (проценты и количество циклов) совпадала. Для сложных сценариев удобнее использовать один общий класс запуска и единый момент добавления этого класса на все нужные элементы (через JS).

Как остановить анимацию в конкретный момент и сохранить текущее состояние элемента

Сделайте промежуточный класс, в котором прописано animation-play-state: paused. При его добавлении анимация останавливается на текущем кадре, потому что браузер просто перестает продвигать время анимации дальше. Если нужно остановить в строго определенный момент по времени, используйте JS — дождитесь нужного времени (таймер или контроль текущего прогресса через вычисления) и в этот момент добавьте класс с animation-play-state: paused.

Стрелочка влевоJavaScript хуки анимаций animation-hooksАнимации во Vue animations - от базовых переходов до сложных сценариевСтрелочка вправо

Постройте личный план изучения Vue до уровня Middle — бесплатно!

Vue — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueИнструкция по установке и компонентам Vue sliderРабота с таблицами во Vue через TanStackУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеИнструкция по работе с grid на VueНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Vuex - полное руководство по управлению состоянием во Vue приложенияхРеактивные ссылки ref - полный разбор для разработчиковРеактивные объекты reactive-objects - подробное руководство с примерамиРеактивные переменные - концепция reactive и практические примерыМеханизм Provide Inject - как он работает и когда применятьPinia современный менеджер состояния для VueЛокальное состояние local state в веб разработкеГлобальное состояние в приложениях - global state
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
Функция append в Go GolangОтображение компонента mounted - практическое руководствоХуки жизненного цикла компонентов - полное руководство для разработчиковУничтожение компонента destroyed - как правильно очищать ресурсы и подпискиИнициализация данных в состоянии created - как и когда подготавливать данные в приложенииОбновление компонента beforeUpdate во VueМонтирование компонента - хук beforeMount в VueРазрушение компонента во Vue - beforeDestroy и beforeUnmountСоздание экземпляра beforeCreate - полный разбор жизненного цикла
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Слоты компонента - концепция и практическое использованиеРегистрация компонентов component-registration в приложениях с внедрением зависимостейProps компонента в React - полный разбор с примерамиФункциональные компоненты в React - функциональный подход к построению интерфейсовСобытия компонента - events в современных интерфейсахДинамические компоненты - dynamic-componentsСоздание компонента component - практическое руководствоАсинхронные компоненты async-components - практическое руководство
Наблюдатели watchers - от паттерна до практических реализацийУправление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsШаблоны Vue templates - практическое руководство для разработчиковИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueРеактивность Vue reactivity - как это работает под капотом и как этим пользоватьсяПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueОпции компонента в Go - паттерн component-optionsРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreВычисляемые свойства computed во Vue.jsСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueОсновы Vue - vue-basics для уверенного стартаИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueТелепортация - архитектура и реализация в серверных приложенияхРабота с teleport для управления DOM во VueSuspense в React - управление асинхронными данными и ленивой загрузкойПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиПлагины Vue vue-plugins - полное практическое руководствоРуководство по nextTick для работы с DOMМиксины - mixins в современном программированииJSX в Vue с использованием плагина vue-jsxСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьКастомные элементы - Custom Elements в современном JavaScriptИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Vue 3 и Pinia

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий