CSS-анимации на основе прокрутки: 5 паттернов анимации прокрутки на чистом CSS без JavaScript

前端工程(Обновлено 14 июл. 2026 г.)

CSS-анимации на основе прокрутки: Плавная прокрутка без JS

Параллакс с JS-слушателями прокрутки вызывает подтормаживания, многословный код IntersectionObserver, накладные расходы производительности requestAnimationFrame — анимации прокрутки долгое время зависели от JavaScript. CSS-анимации на основе прокрутки позволяют реализовать параллакс, индикаторы прогресса и анимации появления исключительно на CSS: ноль JS, 60fps, автоматическое GPU-ускорение. В 2026 году CSS-анимации на основе прокрутки полностью поддерживаются в Chrome и Safari.

Эта статья охватывает 5 основных паттернов, проводя вас через scroll-timeline → view-timeline → параллакс → индикатор прогресса → анимации появления.


Основные концепции

Концепция Описание
scroll-timeline Временная шкала анимации на основе позиции прокрутки
view-timeline Временная шкала анимации на основе видимости элемента
animation-timeline Указывает, какую временную шкалу прокрутки использует анимация
animation-range Начальная и конечная позиции анимации в диапазоне прокрутки
scroll() Анонимная функция временной шкалы прокрутки
view() Анонимная функция временной шкалы видимости
scroll-progress Прогресс прокрутки 0-1
view-progress Прогресс видимости 0-1

Анализ проблем: 5 главных проблем CSS-анимаций прокрутки

  1. Совместимость браузеров: Поддержка Firefox отстаёт
  2. Сложная отладка: Поддержка анимаций прокрутки в DevTools ограничена
  3. Вложенная прокрутка: Конфигурация контейнеров прокрутки, отличных от документа, сложна
  4. Вычисление диапазона анимации: Процент animation-range имеет высокую стоимость понимания
  5. Запасной вариант: Неподдерживаемые браузеры нуждаются в JS-фоллбэке

Пошагово: 5 паттернов CSS-анимаций прокрутки

Паттерн 1: Анимация прогресса прокрутки с scroll-timeline

/* Индикатор прогресса вверху страницы */
@keyframes progress-bar {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: linear-gradient(90deg, #6366f1, #ec4899);
  transform-origin: left;
  animation: progress-bar linear;
  animation-timeline: scroll(root);
}

Паттерн 2: Анимация появления в области просмотра с view-timeline

@keyframes reveal-up {
  from {
    opacity: 0;
    transform: translateY(60px) scale(0.95);
    filter: blur(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
    filter: blur(0);
  }
}

.card {
  animation: reveal-up linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 80%;
}

Паттерн 3: Эффект параллакс-прокрутки

@keyframes parallax-slow {
  from { transform: translateY(0); }
  to { transform: translateY(-100px); }
}

@keyframes parallax-fast {
  from { transform: translateY(0); }
  to { transform: translateY(-300px); }
}

.parallax-bg {
  animation: parallax-slow linear both;
  animation-timeline: scroll(root);
}

.parallax-fg {
  animation: parallax-fast linear both;
  animation-timeline: scroll(root);
}

Паттерн 4: Именованная временная шкала прокрутки

.scroller {
  overflow-y: auto;
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: block;
}

@keyframes rotate-icon {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.rotating-icon {
  animation: rotate-icon linear;
  animation-timeline: --my-scroller;
}

Паттерн 5: Сложные последовательности анимаций

@keyframes hero-sequence {
  0% {
    opacity: 0;
    transform: translateY(100px) scale(0.8);
    filter: blur(10px);
  }
  30% {
    opacity: 1;
    transform: translateY(0) scale(1);
    filter: blur(0);
  }
  70% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  100% {
    opacity: 0;
    transform: translateY(-50px) scale(0.95);
  }
}

.hero-title {
  animation: hero-sequence linear both;
  animation-timeline: view();
  animation-range: entry 0% exit 100%;
}

Руководство по подводным камням

Подводный камень 1: Не указан animation-timeline

/* ❌ Неправильно: отсутствует animation-timeline */
.element {
  animation: slide-in 1s linear;
  /* Анимация не будет следовать за прокруткой */
}

/* ✅ Правильно: указать временную шкалу прокрутки */
.element {
  animation: slide-in linear both;
  animation-timeline: view();
}

Подводный камень 2: Неверные значения animation-range

/* ❌ Неправильно: диапазон превышает диапазон прокрутки */
.element {
  animation-range: entry 0% entry 200%; /* 200% недопустимо */
}

/* ✅ Правильно: использовать допустимый диапазон */
.element {
  animation-range: entry 0% entry 100%;
}

Подводный камень 3: Конфликт transform с прокруткой

/* ✅ Правильно: использовать подсказку will-change */
.parallax {
  animation: parallax linear both;
  animation-timeline: scroll(root);
  will-change: transform;
}

Подводный камень 4: Отсутствие обработки фоллбэка

/* ✅ Правильно: предоставить фоллбэк */
@supports (animation-timeline: view()) {
  .card {
    animation: reveal-up linear both;
    animation-timeline: view();
  }
}

@supports not (animation-timeline: view()) {
  .card { opacity: 1; transform: none; }
}

Подводный камень 5: Контейнер прокрутки без overflow

/* ✅ Правильно: убедиться, что контейнер прокручивается */
.scroller {
  overflow-y: auto;
  scroll-timeline-name: --my-scroll;
}

Устранение ошибок

# Ошибка Причина Решение
1 Анимация не следует за прокруткой Не задан animation-timeline Добавить animation-timeline: view() или scroll()
2 Анимация заканчивается рано animation-range слишком мал Увеличить диапазон
3 Неверное направление параллакса scroll-timeline-axis настроен неверно Использовать block/inline для направления
4 Именованная временная шкала недействительна scroll-timeline-name не совпадает Убедиться, что имена родителя и потомка совпадают
5 Подтормаживание анимации Нет will-change Добавить will-change: transform
6 Firefox не работает Браузер не поддерживает Использовать @supports для фоллбэка
7 Вложенная прокрутка не работает Конфликт внутренней/внешней прокрутки Использовать именованный scroll-timeline
8 Анимация дёргается Ключевые кадры недостаточно плавные Добавить больше ключевых кадров или использовать linear
9 Фиксированные элементы работают некорректно transform влияет на фиксированное позиционирование Переместить фиксированные элементы вне контейнера transform
10 На мобильных не плавно GPU-ускорение не включено Добавить transform: translateZ(0)

Продвинутая оптимизация

  1. Scroll Snap + анимации прокрутки: Комбинация постраничной прокрутки с анимациями
  2. Пользовательские свойства CSS Houdini: Регистрация свойств анимации для сложных эффектов
  3. prefers-reduced-motion: Уважать предпочтение пользователя о снижении движения
  4. Container queries + анимации прокрутки: Синергия адаптивности и анимации прокрутки
  5. WAAPI + Scroll Timeline: Web Animations API в сочетании с CSS-временными шкалами прокрутки

Сравнение

Измерение CSS Scroll-Driven JS IntersectionObserver Событие scroll JS GSAP ScrollTrigger
Производительность ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐
Объём кода ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐
Поддержка браузеров ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Гибкость ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Лёгкость отладки ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
Кривая обучения ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐

Итоги: CSS-анимации на основе прокрутки позволяют достичь плавных эффектов прокрутки с нулём JS, значительно превосходя JS-решения. CSS-анимации прокрутки подходят для сценариев взаимодействия прокрутки, где требуется максимальная производительность, особенно параллакс, индикаторы прогресса и анимации появления. С полной поддержкой Chrome и Safari в 2026 году используйте с фоллбэком @supports.


Онлайн-инструменты

Попробуйте эти локальные браузерные инструменты — регистрация не требуется →

#scroll-timeline#视差效果#滚动动画#CSS动画#2026#前端工程