Анимация появления элементов при загрузке страницы

Чтобы блок или список плавно "выезжал" на экран при открытии страницы, элемент стартует с opacity:0 и небольшим смещением, а animation с fill-mode:forwards доводит его до обычного вида и оставляет так. Для списка добавляется animation-delay на каждый элемент - но без fill-mode:backwards он перед стартом мигнёт, а если элемент вообще ниже экрана, анимация закончится ещё до того, как её кто-то увидит.

Попробуй прямо сейчас: обнови блокнот (или просто подожди - код перерисовывается сам при любом изменении) и три пункта появятся не одновременно, а друг за другом, с нарастающей задержкой в style="animation-delay". Убери строку animation-fill-mode: backwards из .item - и пункты начнут коротко мигать полностью видимыми перед тем, как исчезнуть и заново проявиться, вместо чистого появления из невидимого состояния.

Один блок: opacity, translateY и fill-mode: forwards

Базовый паттерн опирается на уже пройденную механику: @keyframes с явными 0% и 100% задаёт начальное невидимое состояние (opacity:0 и небольшой сдвиг вниз через translateY) и конечное обычное состояние, а animation-fill-mode: forwards оставляет элемент в конечном состоянии после того, как анимация один раз проиграла - без forwards элемент откатился бы обратно к opacity:0 и просто исчез бы сразу после "появления".

.fade-in { opacity: 0; animation: fadeInUp .6s ease-out forwards; } @keyframes fadeInUp { 0% { opacity: 0; transform: translateY(20px); } 100% { opacity: 1; transform: translateY(0); } } - opacity:0 в базовом классе подстраховывает на случай, если анимация ещё не подключилась (например, при медленной загрузке CSS).

.fade-in { animation: fadeInUp .6s ease-out; } @keyframes fadeInUp { 0% { opacity: 0; transform: translateY(20px); } 100% { opacity: 1; transform: translateY(0); } } - fill-mode не указан (по умолчанию none): сразу после конца анимации элемент откатится к исходному opacity, заданному ВНЕ анимации (обычно 1), но конечный 100%-кадр применялся лишь мгновение - в большинстве браузеров визуально это не страшно, однако правило хрупкое и зависит от того, что ничего больше не переопределяет opacity.

Список по очереди: animation-delay и fill-mode: backwards

Чтобы элементы списка появлялись не разом, а друг за другом, у каждого элемента задаётся свой animation-delay - обычно через :nth-child() или инлайновую переменную, растущий с шагом 0.1-0.2s. Но здесь есть подводный камень: animation-delay - это пауза ПЕРЕД стартом анимации, и всё это время элемент по умолчанию виден в своём обычном состоянии, а не в состоянии первого кадра анимации. Из-за этого весь список сначала мелькает полностью видимым, а затем каждый пункт резко "пропадает" и заново плавно проявляется - вместо чистого появления из ничего.

Решение то же самое, что уже разбирали в уроке про animation-fill-mode: значение backwards заставляет элемент выглядеть как на 0%-кадре анимации ещё ДО её реального старта, то есть всю паузу animation-delay элемент остаётся невидимым, а не мелькает. Для списка это обязательная привычка, а не необязательная деталь.

.item:nth-child(1) { animation-delay: .1s; } .item:nth-child(2) { animation-delay: .3s; } .item:nth-child(3) { animation-delay: .5s; } .item { animation: fadeInUp .5s ease-out forwards; animation-fill-mode: backwards; } - во время своей задержки каждый пункт невидим, мигания нет.

.item:nth-child(1) { animation-delay: .1s; } .item:nth-child(2) { animation-delay: .3s; } .item { animation: fadeInUp .5s ease-out forwards; } - fill-mode: backwards не указан: все пункты на мгновение видны целиком, потом резко пропадают и только затем плавно появляются.

Отдельная граница применимости паттерна, которую важно понимать: таймер CSS-анимации при загрузке страницы стартует сразу, как только применились стили - независимо от того, виден ли элемент на экране. Если блок находится далеко от начала страницы (пользователь ещё не долистал), к моменту прокрутки до него однократная анимация уже давно закончится, и он просто появится готовым, без всякого эффекта. Настоящее появление "по мере прокрутки", как на некоторых крупных сайтах, чистым CSS не делается - для отслеживания момента попадания элемента в область видимости нужен JavaScript (обычно IntersectionObserver), это уже за рамками курса про чистый CSS.

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Не указывать animation-fill-mode: forwards для анимации появления После конца анимации элемент откатывается к стилям вне анимации, а не остаётся в конечном виде Всегда добавлять forwards к анимациям появления при загрузке
Задавать animation-delay для списка элементов без fill-mode: backwards Элементы на мгновение видны целиком перед стартом, затем резко пропадают и заново появляются Добавлять animation-fill-mode: backwards (или сокращённо both) к каждому элементу с задержкой
Вешать анимацию появления при загрузке на блок, который находится далеко ниже экрана Анимация проигрывается и заканчивается, пока пользователь ещё не долистал до блока - эффекта никто не увидит Для контента ниже экрана нужен JS с IntersectionObserver, а не анимация при загрузке страницы
Забывать про пользователей с включённым "меньше анимации" в настройках системы Анимация появления может быть навязчивой для части посетителей независимо от их желания Учитывать @media (prefers-reduced-motion: reduce) - подробнее в отдельном уроке курса про доступность

Шпаргалка

ЗаписьЧто означает
opacity:0 + translateY(20px) в 0%-кадреНачальное невидимое и сдвинутое состояние
animation-fill-mode: forwardsЭлемент остаётся в конечном виде после конца анимации
animation-fill-mode: backwardsЭлемент невидим уже во время animation-delay, до старта
.item:nth-child(N) { animation-delay: ... }Каждый элемент списка стартует со своей задержкой - эффект "по очереди"
Элемент ниже экрана + анимация при загрузкеАнимация закончится до того, как пользователь долистает - нужен JS для скролла

Коротко: отвечаем на вопросы

Почему анимация не проигрывается, когда я долистываю до блока внизу страницы?

Потому что таймер CSS-анимации, запущенной при загрузке, стартует сразу, как только применились стили, - независимо от того, виден элемент на экране или нет. Если блок находится далеко от начала страницы, однократная анимация обычно успевает полностью закончиться ещё до того, как пользователь до него долистает, и он появится сразу готовым, без всякого эффекта. Настоящее появление "при попадании в область видимости" чистым CSS не делается - для этого нужен JavaScript с IntersectionObserver, отслеживающим момент прокрутки до элемента.

Нужен ли JavaScript, чтобы анимация появления запустилась при загрузке страницы?

Нет - в отличие от hover-эффектов, которым нужно реальное действие пользователя, CSS-анимация с animation-name начинает играть автоматически, как только браузер применил стили к элементу, без единой строчки JavaScript. JS понадобится только для более сложного сценария - запуска анимации именно в момент прокрутки до конкретного блока, а не сразу при загрузке всей страницы.

Категория
Поделиться в социальных сетях
1. Переходы: transition
2. Трансформации: transform
3. Ключевые кадры и animation
4. Фильтры: filter
5. Практика: живые интерфейсы
6. Производительность и доступность

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×