Back

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

Плавная прокрутка с помощью 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 должно устанавливаться на прокручивающемся контейнере, которому принадлежит viewport, — это элемент html. При применении к body значение не распространяется на скроллер уровня viewport, поэтому прокрутка по якорным ссылкам возвращается к стандартному мгновенному переходу. Перенесите правило на html — и плавная анимация заработает как ожидается.

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

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

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

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. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay