CSS-анимации
Изучите CSS-анимации и управление ими из JavaScript: переключайте классы, реагируйте на события transitionend, animationend и animationiteration.
CSS-анимации предоставляют сложный способ улучшить пользовательский опыт с помощью плавных, визуально привлекательных переходов и эффектов. В этом подробном руководстве мы рассмотрим нюансы CSS-анимаций, приведём детальные объяснения, примеры и лучшие практики для создания динамичных и адаптивных дизайнов.
Введение в CSS-анимации
CSS-анимации позволяют веб-разработчикам анимировать HTML-элементы без использования JavaScript. Они определяются с помощью ключевых кадров, задающих стили в различных точках последовательности анимации.
Базовый пример CSS-анимации
<div class="animated-box"></div>
<style>
.animated-box {
width: 100px;
height: 100px;
background-color: red;
animation: move 4s infinite;
}
@keyframes move {
0% { transform: translateX(0); }
50% { transform: translateX(200px); }
100% { transform: translateX(0); }
}
</style>Всегда тестируйте анимации на разных устройствах и в разных браузерах, чтобы обеспечить плавную работу.
Ключевые свойства CSS-анимаций
animation-name: задаёт имя ключевых кадров.animation-duration: определяет продолжительность анимации.animation-timing-function: задаёт кривую скорости анимации.animation-delay: откладывает начало анимации.animation-iteration-count: определяет количество повторений анимации.animation-direction: указывает, должна ли анимация воспроизводиться в обратном направлении при чередующихся циклах.
Применение нескольких анимаций
К одному элементу можно применить несколько анимаций, разделив их запятыми.
<div class="multi-animated-box"></div>
<style>
.multi-animated-box {
width: 100px;
height: 100px;
background-color: blue;
animation: move 4s infinite, rotate 2s infinite;
}
@keyframes move {
0% { transform: translateX(0); }
50% { transform: translateX(200px); }
100% { transform: translateX(0); }
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>Продвинутые техники
Адаптивные анимации
Убедитесь, что анимации адаптируются к различным размерам экрана.
<div class="responsive-box"></div>
<style>
.responsive-box {
width: 50vw;
height: 50vw;
background-color: green;
animation: resize 4s infinite;
}
@keyframes resize {
0% { width: 50vw; height: 50vw; }
50% { width: 70vw; height: 70vw; }
100% { width: 50vw; height: 50vw; }
}
</style>Комбинирование трансформаций
Объединяйте несколько свойств трансформации для создания сложных анимаций.
<div class="complex-transform-box"></div>
<style>
.complex-transform-box {
width: 100px;
height: 100px;
background-color: yellow;
animation: complexTransform 5s infinite;
}
@keyframes complexTransform {
0% {
transform: translateX(0) rotate(0deg) scale(1);
}
50% {
transform: translateX(200px) rotate(180deg) scale(1.5);
}
100% {
transform: translateX(0) rotate(360deg) scale(1);
}
}
</style>Режимы заполнения анимации
Свойство animation-fill-mode определяет, как CSS-анимация применяет стили к целевому элементу до и после её выполнения.
<div class="fill-mode-box"></div>
<style>
.fill-mode-box {
width: 100px;
height: 100px;
background-color: purple;
animation: fillMode 3s forwards;
}
@keyframes fillMode {
0% { background-color: purple; }
100% { background-color: orange; }
}
</style>Задержки и функции времени анимации
Используйте задержки и функции времени для управления темпом и моментом начала анимаций.
<div class="timing-function-box"></div>
<style>
.timing-function-box {
width: 100px;
height: 100px;
background-color: pink;
animation: timingFunction 4s ease-in-out infinite;
}
@keyframes timingFunction {
0% { transform: translateY(0); }
50% { transform: translateY(200px); }
100% { transform: translateY(0); }
}
</style>Лучшие практики CSS-анимаций
- Минимизируйте нагрузку на CPU: делайте анимации простыми, чтобы избежать избыточного использования CPU, которое может снизить производительность, особенно на мобильных устройствах.
- Используйте аппаратное ускорение: применяйте свойства
transformиopacity, чтобы задействовать ускорение GPU. - Запасные стили: предусмотрите запасные стили для браузеров, не поддерживающих анимации.
- Тестирование производительности: тестируйте анимации на разных устройствах и в разных браузерах для обеспечения плавной работы.
Для создания более интерактивных анимаций можно использовать JavaScript. Смотрите раздел JavaScript-анимации.
Пример хорошо оптимизированной анимации
<div class="optimized-box"></div>
<style>
.optimized-box {
width: 100px;
height: 100px;
background-color: cyan;
animation: optimizedMove 3s ease-in-out infinite;
}
@keyframes optimizedMove {
0% { transform: translateY(0) scale(1); }
50% { transform: translateY(200px) scale(1.2); }
100% { transform: translateY(0) scale(1); }
}
</style>Управление CSS-анимациями из JavaScript
CSS отвечает за отрисовку анимации эффективным образом, но понятия не имеет когда анимация должна запуститься и что должно произойти после её завершения. Эта логика принятия решений принадлежит JavaScript. Наиболее распространённый паттерн: определить анимацию в CSS, а затем позволить JavaScript добавлять или удалять класс для её запуска или остановки.
Это позволяет сохранить плавное воспроизведение с аппаратным ускорением в CSS, пока ваш код контролирует временну́ю последовательность и последующие действия.
Запуск и остановка с помощью переключения класса
Поместите анимацию на класс вместо базового селектора, а затем переключайте этот класс:
<button id="play">Play</button>
<div id="box"></div>
<style>
#box {
width: 100px;
height: 100px;
background: teal;
}
/* The animation only runs while this class is present */
#box.run {
animation: slide 1s ease-in-out;
}
@keyframes slide {
from { transform: translateX(0); }
to { transform: translateX(200px); }
}
</style>
<script>
const box = document.getElementById('box');
document.getElementById('play').onclick = () => {
// Toggle: add the class to play, the CSS animation does the rest
box.classList.add('run');
};
</script>Поскольку анимация привязана к классу .run, удаление этого класса немедленно останавливает её, а повторное добавление запускает с начала.
Добавление и удаление классов анимации — это задача стилизации. Полный набор инструментов смотрите в разделах Стили и классы и Работа со стилями в DOM.
Отслеживание завершения: transitionend и animationend
Ключевое преимущество управления анимациями из JavaScript состоит в том, что браузер генерирует DOM-события, на которые можно реагировать. Это позволяет выстраивать цепочки шагов, очищать классы или выполнять код точно в момент завершения эффекта — без ненадёжных задержек через setTimeout.
- Для CSS переходов событие
transitionendсрабатывает при завершении перехода. - Для CSS анимаций (
@keyframes) срабатывают три события:animationstart,animationiteration(один раз за цикл) иanimationend.
<button id="fade">Fade out</button>
<div id="panel">Hello</div>
<style>
#panel {
width: 150px;
padding: 20px;
background: gold;
transition: opacity 0.5s;
}
#panel.hidden { opacity: 0; }
</style>
<script>
const panel = document.getElementById('panel');
document.getElementById('fade').onclick = () => panel.classList.add('hidden');
// Runs the moment the fade completes — not a guessed delay
panel.addEventListener('transitionend', (event) => {
console.log(`Transition of "${event.propertyName}" finished`);
panel.style.display = 'none'; // safe to hide only now
});
</script>После завершения перехода в консоли появится:
Transition of "opacity" finishedЧтение данных событий: propertyName и animationName
События анимации содержат полезные данные. Когда задействованы несколько свойств или анимаций, часто нужно знать, какая именно только что завершилась.
event.propertyName— CSS-свойство, для которого завершился переход (вtransitionend).event.animationName— имя@keyframes(в трёх событиях анимации).event.elapsedTime— время выполнения в секундах, без учётаanimation-delay.
<div id="bouncer">Watch the console</div>
<style>
#bouncer { animation: bounce 0.6s ease 3; }
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-30px); }
}
</style>
<script>
const el = document.getElementById('bouncer');
el.addEventListener('animationstart', (e) =>
console.log(`start: ${e.animationName}`));
el.addEventListener('animationiteration', (e) =>
console.log(`loop of ${e.animationName} at ${e.elapsedTime}s`));
el.addEventListener('animationend', (e) =>
console.log(`end: ${e.animationName} (total ${e.elapsedTime}s)`));
</script>При animation: bounce 0.6s ease 3 (три итерации) в консоли появятся start, два события animationiteration (начало 2-го и 3-го циклов), затем end при суммарном времени 1.8s.
animationiteration срабатывает между циклами, поэтому для анимации с N повторениями оно сработает N − 1 раз — никогда после последнего цикла. Используйте animationend для определения момента «всё завершено».
JS-управление vs. CSS-управление: что выбрать?
| Используйте CSS-управление (keyframes/переходы), когда… | Используйте JS-управление, когда… |
|---|---|
| Движение фиксировано и декларативно (наведение, загрузчики, появления). | Значения зависят от данных во время выполнения (позиция перетаскивания, прокрутка, физика). |
| Вы хотите наилучшую производительность с минимальным кодом. | Нужен покадровый контроль или возможность поставить на паузу/возобновить на полпути. |
Браузер может перенести работу на GPU (transform, opacity). | Нужно анимировать свойства, которые CSS не может легко выразить. |
Практический гибрид — лучшее из обоих подходов: CSS описывает эффект, JavaScript решает, когда он запускается и что происходит дальше через перечисленные выше события. Когда действительно нужен покадровый контроль, обратитесь к JavaScript-анимациям с requestAnimationFrame или к Web Animations API для создания и управления анимациями полностью в коде.
Заключение
CSS-анимации — это мощный инструмент для создания динамичных и привлекательных веб-интерфейсов. Освоив ключевые кадры, свойства анимации и продвинутые техники, разработчики смогут создавать профессиональные анимации, улучшающие взаимодействие с пользователем. Экспериментируйте с разными анимациями, тщательно тестируйте их и следуйте лучшим практикам для достижения наилучших результатов.