Анимации без JS: CSS уже всё умеет
Новые возможности CSS позволяют делать сложные анимации без JavaScript. Разбираем, что изменилось и как это использовать.
Ещё недавно «появление при прокрутке» или «переход между экранами» означало обработчики событий и кучу JS-кода. Сегодня движки браузеров берут рендер на себя, а мы — описываем намерение в CSS. Плюсы: меньше зависимостей, плавность на уровне композитора, более понятные ограничения производительности.

🚀 Scroll-linked animations: @scroll-timeline
Связываем прогресс анимации с прокруткой. Браузер сам отдаёт «таймлайн» — остаётся привязать к нему keyframes.
@scroll-timeline fade-tl {
source: auto; /* ближайший скроллируемый контейнер */
orientation: block; /* по оси прокрутки */
scroll-offsets: 0%, 100%; /* начало/конец */
}
.section__item{
animation: fade-in 1s both linear;
animation-timeline: fade-tl; /* ← магия */
animation-range: entry 0% cover 60%;/* когда и как играться */
}
@keyframes fade-in {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: translateY(0); }
}
Где использовать: появление карточек, параллакс, прогресс‑бар чтения, sticky‑заголовки секций.
🔁 View Transitions API — «переливы» между состояниями
Нативные переходы между страницами/состояниями без ручной синхронизации. JS запускает транзакцию, CSS оформляет её.
/* CSS */
::view-transition-old(root),
::view-transition-new(root){
animation: fade .35s ease;
}
@keyframes fade {
from { opacity: .001 }
to { opacity: 1 }
}
/* JS (одна строка в обработчике) */
// document.startViewTransition(() => router.navigate('/about'));
Фишка: можно именовать элементы через view-transition-name и делать «перелёт» конкретных блоков (герой‑картинка, заголовок).
📦 Container Queries + анимации
Компоненты реагируют на ширину/высоту родителя, а не всего вьюпорта. Можно плавно «пересобрать» карточку при смене области.
.card{
container-type: inline-size; /* объявили контейнер */
}
@container (min-width: 520px){
.card__media{ inline-size: 280px }
.card__body{ animation: grow .4s ease }
}
@keyframes grow{
from{ transform: scale(.96) }
to { transform: scale(1) }
}
🧲 Селектор состояния :has() без JS
Реакция родителя на состояние/наличие дочерних элементов — триггер для анимации.
.accordion:has(input:checked) .accordion__panel{
grid-template-rows: 1fr; /* раскрываем */
transition: grid-template-rows .3s ease;
}
.accordion:not(:has(input:checked)) .accordion__panel{
grid-template-rows: 0fr; /* скрываем */
}
.card:has(:hover){ transform: rotate(1.5deg) scale(1.03); transition:.25s }
🧩 Индивидуальные transform‑свойства и композиция анимаций
Вместо «большого» transform доступны независимые translate, scale, rotate. А свойство animation-composition позволяет складывать эффекты.
.chip{
translate: 0 8px; /* читаемее и безопаснее */
rotate: 1deg;
transition: translate .25s ease, rotate .25s ease;
}
.chip:hover{ translate: 0 0; rotate: 0deg }
.pulse{ animation: pulse 1.2s infinite ease; }
.float{ animation: float 3s infinite ease alternate; }
.pulse, .float{ animation-composition: add; } /* суммируем эффекты */
@keyframes pulse{ from{scale:1} 50%{scale:1.04} to{scale:1} }
@keyframes float{ from{translate:0 0} to{translate:0 -8px} }
📊 Было/Стало
Задача | Раньше (JS) | Теперь (CSS) |
---|---|---|
Появление при скролле | Обработчик scroll, классы | @scroll-timeline, animation-range |
Параллакс | Прослушка, просчёт позиций | Scroll‑timeline на контейнере |
Переход между страницами | Синхронизация вручную | View Transitions |
Реакция на состояние | События/переключение классов | :has() на родителе |
Компонуем эффекты | Сложные таймлайны в JS | animation-composition: add; |
CSS дорос до уровня, где большинство интерфейсных анимаций создаётся декларативно и работает быстрее. Используйте @scroll-timeline, View Transitions, :has(), Container Queries и индивидуальные transform‑свойства — и оставьте JS там, где нужна логика, а не рендер.
📚 Хочешь углубиться в тему?
В приложении Кодик ты найдёшь подробные уроки по разным темам, пошаговые упражнения, разбор ошибок и удобную практику прямо в телефоне или браузере.
А если хочешь быть в курсе новостей, новых фич и полезных материалов — подписывайся на наш Telegram-канал. Там уютно, по делу и с любовью к коду ❤️
💬 Какие эффекты вы уже перевезли с JS на CSS и что дало больше всего отдачи?