Анимации без JS: CSS уже всё умеет

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

Разработка

6 мин

Ещё недавно «появление при прокрутке» или «переход между экранами» означало обработчики событий и кучу 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 и что дало больше всего отдачи?

Комментарии