Плавный скролл и эффект параллакса: современные методы
Привет! Присаживайся, наливай кофе. Сегодня разберем тему, от которой у фронтендеров старой закалки до сих пор непроизвольно дергается правый глаз. Да-да, я про плавный скролл и параллакс-эффекты.
Дизайнеры обожают эту эстетику: «Пусть эта картинка плывет чуть медленнее, а вот тот заголовок плавно проявляется при прокрутке!». На бумаге звучит круто, но на практике верстальщик часто получал дерганую анимацию, просадки FPS до двузначных чисел и кучу гневных багов в Jira. Но времена изменились. Сегодня, в 2026 году, у нас есть инструменты, которые позволяют делать это элегантно, быстро и без боли для процессора пользователя. Давай разберемся, как скроллить красиво.
Как мы страдали раньше
Вспомни, как мы выкручивались еще несколько лет назад. Стандартный подход выглядел так: мы вешали обработчик на событие window.addEventListener('scroll'). Внутри этого обработчика мы судорожно вычисляли getBoundingClientRect() и двигали элементы через style.transform.
Быстро выяснялось, что событие скролла спамит сотни раз в секунду, намертво забивая главный поток (Main Thread). Начинались костыли:
- Придумывали хитрые обертки с
requestAnimationFrame; - Писали или подключали тяжелые JS-библиотеки для «сглаживания» (scroll hijacking), которые перехватывали управление колесиком мыши;
- Ломали стандартный UX мобильных браузеров, из-за чего пользователи плевались от «кисельного» скролла.
Был еще забавный трюк с чистым CSS на основе 3D-трансформаций (perspective и translateZ). Метод рабочий, но адски сложный в поддержке и масштабировании. Чуть-чуть изменилась высота контейнера — и вся магия ломалась, а адаптив превращался в ночной кошмар.
Как делать правильно в 2026 году
Забудь про JS-расчеты для простых визуальных эффектов. На дворе эра Scroll-driven Animations (анимаций, управляемых прокруткой) на чистом CSS. Браузеры теперь умеют связывать прогресс анимации напрямую с положением скроллбара на уровне движка.
Главный плюс: вычисления происходят в композитном потоке (Compositor Thread). Даже если тяжелый скрипт на секунду заблокирует основной поток JS, параллакс продолжит работать плавно со скоростью 120 кадров в секунду.
В основе современного подхода лежат два ключевых понятия:
scroll()— привязывает анимацию к общему прогрессу прокрутки контейнера;view()— запускает анимацию в зависимости от того, где именно элемент находится внутри области видимости (viewport). Для параллакса отдельных блоков это идеальный вариант.
Чтобы анимация выглядела безупречно на любых экранах, не забывай про гибкую верстку. Тут нам очень пригодятся математические функции в CSS: clamp, min, max — они помогут задать жесткие границы для смещения элементов, чтобы они не улетали за пределы экрана на ультрашироких мониторах.
И еще один лайфхак: если нужно передавать динамические параметры скролла в разные компоненты, свяжи их с CSS-переменными. Это так же удобно, как настройка кастомных свойств для динамического изменения тем — код остается чистым, декларативным и легко масштабируемым.
Готовый сниппет кода
Давай соберем лаконичный пример. Мы сделаемhero-секцию с эффектом параллакса для фонового изображения и заголовка на чистом CSS. Без единой строчки JavaScript.
<!DOCTYPE html>
<html lang="ru">
<head>
<style>
/* Базовые стили для плавной прокрутки */
html {
scroll-behavior: smooth;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
background-color: #0f172a;
color: #f8fafc;
}
/* Контейнер секции */
.parallax-section {
position: relative;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
/* Определяем область видимости анимации для дочерних элементов */
view-timeline-name: --section-timeline;
view-timeline-axis: block;
}
/* Фоновое изображение с эффектом параллакса */
.parallax-bg {
position: absolute;
top: -20%;
left: 0;
width: 100%;
height: 140%;
background-image: url('https://picsum.photos/id/1015/1920/1080');
background-size: cover;
background-position: center;
z-index: 1;
will-change: transform;
/* Связываем анимацию со скроллом нашей секции */
animation: parallax-move linear;
animation-timeline: --section-timeline;
/* Начинаем двигать, как только показался низ секции, заканчиваем, когда секция ушла */
animation-range: exit-crossing;
}
/* Заголовок, который движется быстрее фона */
.parallax-title {
position: relative;
z-index: 2;
font-size: clamp(2rem, 8vw, 5rem);
text-transform: uppercase;
font-weight: 900;
text-shadow: 0 10px 30px rgba(0,0,0,0.5);
will-change: transform, opacity;
animation: title-fade-and-move linear;
animation-timeline: --section-timeline;
animation-range: exit-crossing;
}
/* Обычный контент ниже, чтобы было куда скроллить */
.content-section {
height: 100vh;
padding: 4rem 2rem;
max-width: 800px;
margin: 0 auto;
font-size: 1.25rem;
line-height: 1.8;
}
/* Описание ключевых кадров для анимации скролла */
@keyframes parallax-move {
from {
transform: translateY(0);
}
to {
transform: translateY(20%);
}
}
@keyframes title-fade-and-move {
from {
transform: translateY(0);
opacity: 1;
}
to {
transform: translateY(-50px);
opacity: 0;
}
}
/* Важно: отключаем анимации, если пользователь просит об этом в системе */
@media (prefers-reduced-motion: reduce) {
.parallax-bg, .parallax-title {
animation: none;
}
}
</style>
</head>
<body>
<section class="parallax-section">
<div class="parallax-bg"></div>
<h1 class="parallax-title">Вперед в будущее</h1>
</section>
<section class="content-section">
<h2>Новая эра веб-эффектов</h2>
<p>Этот параллакс работает без единой строчки JS-кода. Браузер сам рассчитывает смещение слоев в композитном потоке, гарантируя стабильные 60+ кадров в секунду даже на мобильных устройствах. Мы просто связали ключевые кадры анимации с прогрессом скролла контейнера с помощью свойства <code>animation-timeline</code>.</p>
</section>
</body>
</html>
Частая ошибка новичков
Самый частый факап при реализации параллакса — это игнорирование оптимизации и доступности (Accessibility).
Во-первых, анимация больших фонов нагружает видеокарту. Всегда добавляй свойство will-change: transform (или will-change: opacity) для анимируемых слоев. Это подскажет браузеру, что элемент нужно вынести на отдельный слой в GPU заранее, избегая микрофризов при первом рендере. Но не переусердствуй: пихать will-change на все элементы подряд — верный способ забить память девайса.
Во-вторых (и это самое важное!), помни про вестибулярный аппарат пользователей. Некоторых людей от резкого или интенсивного параллакса банально укачивает. Всегда оборачивай свои скролл-анимации в медиа-запрос @media (prefers-reduced-motion: reduce). Если у пользователя в настройках ОС включен режим уменьшения движения, сайт должен мгновенно отключать все летающие слои и вести себя статично. Это признак действительно профессиональной, «сениорской» разработки.
Используй современные стандарты, береги нервы пользователей и пиши чистый код без лишних библиотек там, где браузер уже умеет всё сам!
🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!