Подробные статьи о технологиях, определяющих будущее.

Scroll Fade — антипаттерн UX, от которого пора отказаться

Анимации появления при скролле вредят юзабилити, замедляют страницы и раздражают пользователей. Почему паттерн живёт и что использовать вместо него.

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

Вы видели это на каждом маркетинговом сайте, лендинге SaaS-продукта и портфолио за последние пять лет. Вы прокручиваете страницу, и контент проступает снизу, выезжает сбоку или появляется из ниоткуда, как только попадает в область видимости. Иногда с задержкой, так что каждый элемент выходит по очереди, как кордебалет. Разработчики, которые это сделали, считают, что выглядит «премиально». А пользователи просто хотят почитать страницу.

Анимации появления при скролле, которые некоторые разработчики называют «scroll reveal», стали одним из самых распространённых паттернов в вебе. Они же одни из самых враждебных к пользователю. Они замедляют воспринимаемую скорость, ломают доступность, мешают просматривать контент и ничего не добавляют к пониманию страницы. Пора перестать их использовать.

Аргументы против scroll fade

Проблемы scroll fade не мелкие. Они фундаментальные.

Контент невидим, пока вы до него не доскроллили. Звучит очевидно, но подумайте, что это значит. Если пользователь быстро прокручивает страницу, чтобы найти конкретный раздел, например таблицу тарифов, сравнение функций или техническую спецификацию, он видит пустоту, пока анимации не догонят. Контент есть в DOM, но спрятан за opacity: 0 и CSS-переходом, который ещё не сработал. Быстрые скроллеры не видят ничего. Те, кто ищет по странице (Ctrl+F), попадают на невидимый текст. А некоторые вспомогательные технологии вообще могут не вызвать события скролла.

Наказывает быстрых читателей. Поэлементное появление заставляет пользователя ждать, пока каждый блок выйдет по очереди, независимо от того, насколько быстро он способен воспринимать текст. Опытный читатель, который сканирует страницу в поисках нужной информации, искусственно замедляется до темпа анимации. Задержка 300 мс на элемент в разделе из пяти пунктов означает 1,5 секунды принудительного ожидания, а это целая вечность, когда вы оцениваете продукт.

Ломает кнопку «Назад». Открываете страницу, прокручиваете до середины, переходите по ссылке и жмёте «Назад». Во многих реализациях scroll fade страница возвращается с уже показанным контентом снова невидимым, и приходится заново прокручивать то, что вы уже видели, чтобы анимации сработали.

Налог на производительность

Анимации scroll fade имеют реальную цену для производительности, даже «оптимизированные». Intersection Observer API лучше, чем слушатели событий скролла, но паттерн всё равно требует JavaScript, который вычисляет пересечения и меняет DOM при прокрутке. На странице с 50 элементами с fade-in это 50 наблюдателей, которые срабатывают при каждом скролле.

// The "modern" approach — still problematic
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
// Each of these triggers a style recalculation
// and potentially a layout/paint operation
}
});
}, { threshold: 0.1 });
// Observing 50+ elements on a landing page
document.querySelectorAll('.fade-in').forEach(el => {
observer.observe(el);
});
// Plus the CSS:
// .fade-in { opacity: 0; transform: translateY(20px); transition: 0.6s; }
// .fade-in.visible { opacity: 1; transform: translateY(0); }

Более серьёзная проблема производительности связана с Cumulative Layout Shift (CLS). Элементы, которые стартуют с opacity: 0 и смещением translateY, а затем анимируются в финальную позицию, могут вызывать сдвиги вёрстки, если их аккуратно не обработать. Core Web Vitals от Google штрафуют за это. Многие реализации scroll fade ухудшают показатель CLS, а он бьёт по позициям в поиске, то есть ровно противоположно тому, чего хотят маркетинговые сайты.

И есть ещё первоначальный рендер: контент изначально скрыт. Если JavaScript не загрузился, его заблокировал блокировщик рекламы (иногда они цепляют библиотеки анимаций) или он выбросил ошибку, контент остаётся невидимым навсегда. Ваш «премиальный» лендинг превращается в пустую страницу.

Ущерб для доступности

Пользователи с вестибулярными расстройствами, а это примерно 35% взрослых старше 40 лет, могут испытывать головокружение, тошноту или дезориентацию от анимаций движения. Медиа-запрос prefers-reduced-motion как раз существует для этого, но многие реализации scroll fade его полностью игнорируют.

/* The bare minimum, which most sites skip */
@media (prefers-reduced-motion: reduce) {
.fade-in {
opacity: 1 !important;
transform: none !important;
transition: none !important;
}
}

Даже при уважении к prefers-reduced-motion остаются более глубокие проблемы доступности. Экранные читалки ориентируются по заголовкам, ориентирам и ссылкам, а не по скроллу. Если контент скрыт до срабатывания события прокрутки, пользователи читалок могут натыкаться на невидимые элементы или слышать анонсы того, что зрячий пользователь пока не видит. Это сбивает с толку тех, кто опирается и на звук, и на зрение.

С навигацией с клавиатуры та же история. Перемещаясь по странице с помощью Tab, вы фокусируетесь на невидимых ссылках и кнопках. Контур фокуса появляется на прозрачном элементе. Пользователь понятия не имеет, на чём он сейчас находится.

Почему паттерн живёт

Если scroll fade так проблематичен, почему он повсюду? Три причины.

Во-первых, в демо он хорошо выглядит. Когда дизайнер или разработчик показывает лендинг заказчикам, он медленно прокручивает страницу, и все смотрят. Анимации кажутся осмысленными и премиальными. Но так пользователи не просматривают сайты. Они скроллят быстро, прыгают по странице, пользуются поиском, ориентируются по заголовкам. Демо-сценарий, то есть медленная линейная прокрутка при первом визите, оказывается самым редким реальным сценарием.

Во-вторых, так делают все конкуренты. Scroll fade стал признаком «современного веб-дизайна». Если его не использовать, сайт выглядит статичным, а заказчики считают это устаревшим. Это чистый карго-культ: анимации не выполняют функции, они удовлетворяют эстетические ожидания, созданные другими сайтами, которым они тоже не нужны.

В-третьих, шаблоны и библиотеки компонентов включают его по умолчанию. Framer Motion, AOS, ScrollReveal, GSAP ScrollTrigger делают скролл-анимации тривиально простыми. Когда добавить анимацию можно одной строкой атрибута, её добавляют везде. Стоимость внедрения настолько низкая, что никто не останавливается и не спрашивает, нужна ли эта анимация пользователю.

Когда анимация действительно полезна

Движение само по себе не плохо. Анимация — законный инструмент интерфейса, когда она выполняет одну из этих задач:

  • Показ причинно-следственной связи. Нажатие кнопки, после которого выезжает панель, показывает связь между действием и результатом. Это помогает пользователю построить ментальную модель интерфейса.
  • Привлечение внимания. Едва заметная пульсация на значке уведомления направляет взгляд к новой информации. Это проактивно: система сама привлекает внимание, а не реагирует на скролл.
  • Сохранение пространственного контекста. Анимированные переходы между экранами (например, push/pop в навигации iOS) помогают понять, где вы находитесь в иерархии. Без анимации смена выглядит резкой.
  • Обратная связь. Спиннер загрузки, индикатор прогресса, скелетон-экран сообщают пользователю, что что-то происходит. Они снижают воспринимаемое время ожидания.

Обратите внимание, что у всех этих случаев есть общее: анимация передаёт информацию. Она помогает пользователю понять интерфейс. Scroll fade не делает ни того, ни другого, он чисто декоративен. Контент, который выезжает снизу, ничего не говорит пользователю ни о связи элемента с другими элементами, ни о его важности. Это движение ради движения.

Что делать вместо этого

Если вы хотите, чтобы страницы выглядели динамично без минусов scroll fade, вот подходы, которые реально работают.

Просто покажите контент. В 90% случаев это лучший вариант. Контент, который сразу виден, можно читать, искать и сканировать. Хорошо продуманная вёрстка с качественной типографикой, понятной иерархией и аккуратными отступами выглядит лучше страницы, перегруженной анимациями, и при этом быстрее грузится, доступнее и не ломается, если JavaScript упал.

Используйте CSS-анимации, привязанные к скроллу. Новые свойства animation-timeline: scroll() и animation-timeline: view() позволяют создавать эффекты, привязанные к прокрутке, без JavaScript. Они ускоряются на GPU, не вызывают сдвигов вёрстки и корректно деградируют. Если без движения при скролле никак не обойтись, то именно так и стоит это делать.

/* CSS scroll-driven animation — no JavaScript needed */
.parallax-bg {
animation: parallax linear;
animation-timeline: scroll();
}
@keyframes parallax {
from { transform: translateY(0); }
to { transform: translateY(-50px); }
}
/* Respects user preferences automatically */
@media (prefers-reduced-motion: reduce) {
.parallax-bg {
animation: none;
}
}

Анимируйте по взаимодействию, а не по скроллу. Эффекты при наведении, реакции на клик, состояния фокуса запускаются намерением пользователя и дают прямую обратную связь. Они ощущаются отзывчивыми, а не театральными. Карточка, которая чуть приподнимается при наведении, сообщает: «это интерактивно». Карточка, которая появляется при скролле, не сообщает ничего.

Используйте переходы для смены состояний. Когда контент действительно появляется из-за действия пользователя (раскрывается аккордеон, открывается модальное окно, фильтруется список), анимируйте этот переход. Он показывает причину и следствие. Это принципиально отличается от контента, который всегда был на месте, но искусственно скрывался до тех пор, пока вы не доскроллите. Кто сталкивался с распространёнными UX-антипаттернами, знает: разница между функциональной и декоративной анимацией имеет огромное значение.

Расстаёмся с любимыми идеями

Самое сложное в отказе от scroll fade не техническое. Сложно убедить заказчиков (или себя), что страница без него выглядит лучше. Нас приучили связывать движение с качеством. Статичная страница кажется недоделанной по сравнению с той, где есть скролл-анимации, хотя статичная быстрее, доступнее и удобнее.

Попробуйте такое упражнение: возьмите страницу, перегруженную scroll fade, и отключите все анимации. Просто покажите всё сразу. Потом спросите себя: потерялась ли какая-то информация? Стала ли менее понятна связь между элементами? Стала ли страница труднее для понимания? Ответ почти всегда «нет». Анимации были декорацией. Контент держится и сам по себе.

Если вашему контенту нужна анимация, чтобы выглядеть убедительно, проблема не в отсутствии анимации, а в самом контенте. Исправьте контент.