ФронтендHTML / CSS

CSS-анимация при прокрутке без JavaScript: scroll-driven animations

Создаём индикатор чтения и появление карточек на чистом CSS через scroll() и view(), настраиваем диапазоны и безопасный fallback.

Кодик

Автор

6 мин чтения

scroll-driven animations можно освоить на одном небольшом проекте, если сразу видеть вход, действие и результат. Scroll-driven animations связывают прогресс CSS-анимации с прокруткой документа или появлением элемента в области просмотра. Ниже вы соберёте работающий пример и проверите обычный и граничный сценарии.

Обработчик scroll на JavaScript легко запускается слишком часто, смешивает измерения и стили и дёргает интерфейс на слабом устройстве. Поэтому отделим настройку, входные данные, основное действие и проверку. В этой статье вы соберёте страницу статьи с индикатором чтения сверху и мягким появлением карточек по мере прокрутки. Проверка: полоса растёт от 0 до 100 процентов, карточки появляются в заданном диапазоне, а без поддержки весь текст остаётся видимым.

1Соберите минимум

создать progress и несколько карточек в длинной статье. Не расширяйте проект до первого успешного запуска.

2Увидьте данные

полоса растёт вместе с документом. Проверяйте значение, а не отсутствие ошибки.

3Измените правило

После успеха измените диапазон появления карточки и предскажите точку завершения до запуска. Так копирование станет практикой.

Как устроен учебный проект scroll-driven animations

Одна анимация использует scroll timeline документа, другая создаёт view timeline для каждой карточки. CSS связывает timeline с keyframes. Держите ввод, логику и отображение раздельно: тогда каждый этап можно проверить отдельно.

ЭтапДействиеПроверяемый результат
Разметкасоздать progress и несколько карточек в длинной статьеконтент полностью читается без анимации
Индикаторсвязать scaleX с animation-timeline: scroll()полоса растёт вместе с документом
Карточкииспользовать view() и animation-rangeэлемент появляется при входе в viewport
Fallbackобернуть улучшение в @supports и reduced motionнеподдерживаемый браузер показывает обычную страницу

Контрольные точки: разметка, индикатор, карточки и fallback. Следующий шаг начинается после совпадения с ожидаемым результатом.

Путь данных в проекте scroll-driven animations
От входных данных до видимого результата. Сначала проверяется вход, затем действие и только потом интерфейс.

Зафиксируйте первый успех До добавления animation-timeline убедитесь, что у progress правильные fixed-позиция, transform-origin и конечный видимый цвет. Сохраните команду запуска и ожидаемый вывод.

Собираем рабочий пример шаг за шагом

Пример сверялся с актуальной документацией MDN Scroll-driven animations на 19 октября 2026 года. Создайте один index.html и styles.css, затем откройте через локальный сервер в актуальном браузере. Проверьте текущую папку через pwd или Get-Location. Вставьте пример целиком, выполните один раз, затем разбирайте по частям.

.reading-progress {
  position: fixed;
  inset: 0 0 auto;
  height: 6px;
  background: #0d7cff;
  transform: scaleX(0);
  transform-origin: left;
  animation: reading linear;
  animation-timeline: scroll();
}

@keyframes reading {
  to { transform: scaleX(1); }
}

@supports (animation-timeline: view()) {
  .lesson-card {
    animation: reveal both linear;
    animation-timeline: view();
    animation-range: entry 10% cover 35%;
  }
}

@keyframes reveal {
  from { opacity: 0; transform: translateY(24px); }
  to { opacity: 1; transform: translateY(0); }
}
Что должно произойти после запуска
  • Синяя полоса сверху пропорциональна общей прокрутке документа.
  • Каждая карточка анимируется собственной view timeline только при входе в область просмотра.
  • Повторный запуск даёт тот же предсказуемый результат.
  • Пустой ввод получает понятное сообщение вместо падения.

scroll() измеряет прокрутку контейнера, а view() измеряет положение конкретного элемента относительно scrollport. Найдите в примере вход, проверку и место формирования результата.

Хрупкий и проверяемый вариант scroll-driven animations
Что отличает устойчивый проект от случайного запуска. Явные границы делают ошибку локальной и понятной.

Что происходит внутри и почему это работает

Обычная временная анимация меняется от 0 до duration. Здесь роль времени играет прогресс прокрутки. animation-range выбирает часть timeline, в которой keyframes проходят от начала до конца. Логику держите отдельно от вывода: функция получает аргумент и возвращает значение, а интерфейс показывает его. Флаг both сохраняет начальное и конечное состояния вне активного диапазона, но базовый CSS не должен делать контент невидимым в браузере без поддержки.

ЧастьЗа что отвечаетЧто проверить
Keyframesописывают начальный и конечный визуальный видконечный кадр читаем и не меняет layout
Timelineзадаёт источник прогресса scroll() или view()анимация движется только при прокрутке
Rangeограничивает участок входа и покрытия элементаэффект заканчивается до центра экрана

Для плавности меняйте transform и opacity, а не высоту и позиционные свойства, вызывающие перерасчёт layout. Не связывайте с прокруткой жизненно важные элементы управления. Пользователь должен видеть кнопку и читать текст независимо от эффекта. Не прячьте поток в одном обработчике: сохраните вход, проверьте его, вызовите операцию и только затем обновите интерфейс.

Проверьте границу Удалите блок @supports и откройте страницу в браузере без функции. Если карточки стали невидимыми, fallback построен неправильно. Меняйте одно условие за прогон, чтобы видеть причину.

Проверяем проект и добавляем свою функцию

Добавьте шкалу прогресса внутри одного длинного раздела через именованный scroll timeline и сравните её с прогрессом всей страницы. До правки запишите ожидаемое поведение одним предложением. После граничного теста повторите обычный сценарий.

Проверка своими руками
  1. Сохраните ожидаемый результат: полоса растёт от 0 до 100 процентов, карточки появляются в заданном диапазоне, а без поддержки весь текст остаётся видимым.
  2. Измените правило: измените диапазон появления карточки и предскажите точку завершения до запуска. Сначала предскажите итог.
  3. Передайте граничное значение и убедитесь, что приложение не падает.
  4. Верните корректные данные и объясните роли трёх основных частей.
Готово, если выполняются все пункты
  • контент полностью читается без анимации
  • полоса растёт вместе с документом
  • элемент появляется при входе в viewport
  • неподдерживаемый браузер показывает обычную страницу

CSS timeline убирает ручной scroll listener, но дизайн диапазона и доступности всё равно остаётся задачей разработчика. Полезная правка проходит от нового ввода до видимого результата.

Четыре контрольные точки scroll-driven animations
Четыре проверки перед следующим шагом. Каждый следующий этап начинается после наблюдаемого результата.

Что запомнить и куда двигаться дальше

Проверьте клавиатурную прокрутку, мобильную ширину, reduced motion и очень короткую страницу. Индикатор не должен перекрывать фокус и навигацию. Для закрепления откройте в статье про тёмную тему, в View Transitions API и в практическом лендинге.

Как изучить тему в Кодике

Повторите keyframes, transform, overflow и viewport, затем добавляйте timeline. Сначала восстановите главную функцию и проверьте её на трёх значениях.

ШагЧто разобратьМини-проверка
1. ОсноваCSS-анимации, transform и fixed-позиционированиеОбъясните вход и выход функции.
2. Инструментscroll(), view() и animation-rangeПовторите команду по памяти.
3. ПроектИндикатор чтения и появление карточекПроверьте два сценария.
4. РефакторингИменованные timeline и тест доступностиРазделите ввод, логику и вывод.

Попробуйте убрать JavaScript-обработчик из старого демо, сохранив тот же результат и хороший fallback. Базовый синтаксис закрепите через курс CSS.

Скрытый fallback

Opacity: 0 применяется всегда, а timeline не поддерживается. Помещайте улучшение в @supports.

Анимация layout-свойств

Изменение top или height может дёргать страницу. Используйте transform и opacity.

Слишком длинный range

Карточка остаётся полупрозрачной слишком долго. Завершайте эффект раньше.

Нет reduced motion

Прокручиваемое движение может мешать. Отключайте или сокращайте эффект.

Сверяйтесь с первичной документацией. Команды и ограничения примера проверены по MDN Scroll-driven animations. Если версия инструмента изменилась, официальный источник важнее старого скриншота.

Что получится в итоге

Готовый результат проекта: CSS-анимация при прокрутке без JavaScript: scroll-driven animations
Так выглядит законченный учебный проект: есть понятный вход, видимый результат, защита от неверных данных и место для следующего улучшения.

Короткие ответы
Чем scroll() отличается от view()?

scroll() связан с прогрессом прокрутки контейнера, view() с положением конкретного элемента в области просмотра.

Нужен ли requestAnimationFrame?

Нет. Прогрессом управляет CSS timeline браузера.

Что проверять первым, если scroll-driven animations не запускается?

Версию среды, текущую папку, команду запуска и первую строку ошибки.

Как понять, что проект scroll-driven animations работает?

Проверьте основной сценарий, неверный ввод, повторный запуск и один граничный случай.

Можно ли начать с готового кода?

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

Сделайте один осознанный шаг дальше

Выберите одно улучшение и проведите его от ввода до результата.

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