12k
All articles

Плавная прокрутка с помощью CSS scroll-behavior

Используйте CSS scroll-behavior: smooth для якорных ссылок, уберите перекрытие фиксированным хедером с scroll-margin-top и учтите доступность.

OpenReplay Team
OpenReplay Team
Плавная прокрутка с помощью CSS scroll-behavior

Клик по якорной ссылке и мгновенный переход страницы к нужному разделу выглядит резко. Это дезориентирует пользователей, нарушает поток чтения и делает внутристраничную навигацию неаккуратной. Решение — одно-единственное CSS-свойство, без всяких JavaScript-библиотек.

Ключевые моменты

  • CSS-свойство scroll-behavior: smooth включает анимированную прокрутку для якорных ссылок и программных scroll-API без какого-либо JavaScript.
  • Применяйте его к элементу html, а не body, чтобы свойство корректно распространялось на область просмотра (viewport).
  • Управляемые браузером функция сглаживания и длительность не настраиваются через CSS — прибегайте к JavaScript только тогда, когда нужен тонкий контроль.
  • Используйте scroll-margin-top, чтобы фиксированные шапки не закрывали якорные цели.
  • Оборачивайте правило в медиа-запрос prefers-reduced-motion: no-preference, чтобы учитывать настройки доступности.

Что такое scroll-behavior и как оно работает?

CSS-свойство scroll-behavior управляет тем, как прокручивающийся контейнер перемещается, когда прокрутка инициирована программно — через якорные ссылки, навигацию по хэшу или JavaScript-API прокрутки, такие как window.scrollTo() или element.scrollIntoView().

Оно принимает два значения:

  • auto — значение по умолчанию. Прокрутка происходит мгновенно, без анимации.
  • smooth — анимирует прокрутку с использованием функции сглаживания и длительности, определённых браузером.

Важное уточнение: scroll-behavior не влияет на прокрутку, инициированную колесом мыши, тачпадом или перетаскиванием полосы прокрутки. Оно применяется только к прокрутке по якорям и программной прокрутке.

Функция сглаживания и длительность полностью контролируются браузером. Настроить их только средствами CSS невозможно. Если вам нужна конкретная длительность или собственная кривая сглаживания, понадобится решение на JavaScript.

Добавление плавной CSS-прокрутки на страницу

Примените scroll-behavior: smooth к элементу html, чтобы включить плавную прокрутку навигации по всей странице:

html {
  scroll-behavior: smooth;
}

Используйте html, а не body. При установке на корневом элементе свойство применяется к области просмотра. Установка на body не распространяется на viewport — это частый источник путаницы, когда плавная прокрутка не работает.

Это единственное объявление автоматически обрабатывает прокрутку по всем якорным ссылкам. Без JavaScript, без зависимостей.

Практические случаи использования

Навигация по оглавлению:

<nav>
  <a href="#intro">Introduction</a>
  <a href="#usage">Usage</a>
  <a href="#examples">Examples</a>
</nav>

Кнопка «Наверх»:

<a href="#top">↑ Back to top</a>

Чтобы ссылка «наверх» приводила в самый верх страницы, убедитесь, что элемент с id="top" существует в начале страницы, либо используйте href="#" в качестве запасного варианта. Оба подхода работают сразу же после установки scroll-behavior: smooth на html.

Обработка фиксированных шапок с помощью scroll-margin-top

Если в вашей вёрстке присутствует фиксированная шапка, якорные цели будут частично прокручиваться под неё. Это исправляется с помощью scroll-margin-top:

:target {
  scroll-margin-top: 80px; /* match your header height */
}

Для более широкого охвата — включая программную прокрутку к элементам, которые не являются текущим :target, — применяйте правило непосредственно к самим секциям:

section[id] {
  scroll-margin-top: 80px;
}

Это смещает позицию, в которой браузер останавливается при переходе к целевому элементу, — без необходимости в JavaScript.

Доступность: учёт prefers-reduced-motion

Некоторые пользователи испытывают укачивание или вестибулярный дискомфорт, вызываемый анимированной прокруткой. Всегда учитывайте медиа-запрос prefers-reduced-motion:

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

Этот шаблон включает плавную прокрутку только для пользователей, которые не отказались от анимации в настройках своей ОС. Это рекомендуемый подход для доступного UX прокрутки.

Поддержка браузерами

scroll-behavior имеет универсальную поддержку во всех современных браузерах — Chrome 61+, Firefox 36+, Edge 79+, Safari 15.4+ и Opera 48+. Глобальный уровень поддержки составляет около 95%, поэтому полифилы для текущих проектов не нужны.

CSS или JavaScript: что выбрать?

ПотребностьЛучший подход
Простая прокрутка по якорным ссылкамCSS
Кастомная длительность или сглаживаниеJavaScript
Условная или логически управляемая прокруткаJavaScript

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

Краткий чек-лист реализации

  • ☐ Примените scroll-behavior: smooth к html, а не к body
  • ☐ Оберните его в prefers-reduced-motion: no-preference
  • ☐ Добавьте scroll-margin-top для макетов с фиксированной шапкой
  • ☐ Протестируйте якорные ссылки и навигацию с клавиатуры
  • ☐ Проверьте поведение в iOS Safari

Заключение

Плавная CSS-прокрутка — одно из тех улучшений, которое почти ничего не стоит реализовать, но сразу же делает внутристраничную навигацию более продуманной. Одно правильно размещённое объявление покрывает большинство реальных сценариев использования без обращения к JavaScript.

Часто задаваемые вопросы

Почему scroll-behavior smooth не работает, когда я устанавливаю его на элемент body?

Свойство scroll-behavior должно устанавливаться на прокручивающемся контейнере, которому принадлежит viewport, — это элемент html. При применении к body значение не распространяется на скроллер уровня viewport, поэтому прокрутка по якорным ссылкам возвращается к стандартному мгновенному переходу. Перенесите правило на html — и плавная анимация заработает как ожидается.

Можно ли управлять скоростью или функцией сглаживания плавной CSS-прокрутки?

Нет. Длительность анимации и кривая сглаживания полностью определяются браузером и не поддаются настройке через CSS. Если вашему дизайну требуется конкретная скорость или собственная функция сглаживания, нужно решение на JavaScript с использованием window.scrollTo с behavior smooth в сочетании с собственной логикой анимации, либо небольшая библиотека, которая обрабатывает тайминг вручную.

Влияет ли scroll-behavior smooth на прокрутку колесом мыши и тачпадом?

Нет. Свойство применяется только к программной и инициируемой якорями прокрутке — например, при клике по хэш-ссылке, вызове scrollIntoView или window.scrollTo. Прокрутка, инициированная пользователем через колесо мыши, жесты тачпада, перетаскивание полосы прокрутки или стрелки клавиатуры, остаётся незатронутой и продолжает использовать нативное поведение прокрутки браузера.

Как предотвратить перекрытие якорной цели фиксированной шапкой?

Используйте свойство scroll-margin-top на целевом элементе со значением, равным высоте вашей шапки. Например, установка scroll-margin-top равным 80px на элементах section с id смещает позицию остановки прокрутки так, чтобы раздел оказался ниже фиксированной шапки, а не скрывался под ней. JavaScript или дополнительная разметка при этом не требуются.

Open-source session replay

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.