Чтобы сделать плавный скролл на CSS, добавьте в стили одну строку: html { scroll-behavior: smooth; }. После этого клик по якорной ссылке вида <a href="#price"> не перебрасывает страницу рывком, а прокручивает её к нужному блоку. JavaScript для этого не нужен.
Ниже разберём, куда именно ставить свойство, как не спрятать заголовок под фиксированной шапкой и когда без JavaScript всё-таки не обойтись. Если вы только начинаете со стилями, сначала пригодится разбор что такое CSS и как он устроен.
Как сделать плавный скролл к якорю на чистом CSS

Плавная прокрутка к якорю собирается из трёх частей: ссылки, блока с id и одного свойства в CSS. Порядок такой.
- Дайте целевому блоку атрибут
id, например<section id="price">. - Поставьте на него ссылку с решёткой:
<a href="#price">Цены</a>. Как устроены сами ссылки и атрибутhref, подробно описано в статье про тег a в HTML. - Добавьте в CSS правило для корневого элемента
html. - Обновите страницу и кликните по ссылке: страница поедет к блоку, а не прыгнет.
<nav>
<a href="#about">О нас</a>
<a href="#price">Цены</a>
</nav>
<section id="about">…</section>
<section id="price">…</section>
html {
scroll-behavior: smooth;
}
У свойства два рабочих значения. auto стоит по умолчанию и прокручивает мгновенно, smooth включает анимацию. Если правило не срабатывает, первым делом проверьте, что файл стилей вообще подключён: три способа и быстрая проверка есть в инструкции как подключить CSS к HTML.
Скорость и кривую анимации в CSS не задать. По справке MDN, функцию сглаживания и длительность определяет браузер.
Плавная прокрутка внутри блока
Свойство работает не только для всей страницы. Его можно повесить на любой контейнер со своей полосой прокрутки: список сообщений в чате, ленту карточек, длинную таблицу.
.chat {
height: 400px;
overflow-y: auto;
scroll-behavior: smooth;
}
Здесь плавной станет прокрутка только внутри .chat. На саму страницу правило не влияет, и наоборот: scroll-behavior у html не делает плавными вложенные контейнеры.
Как не спрятать заголовок под фиксированной шапкой

Частая картина: шапка сайта закреплена через position: fixed, вы кликаете по якорю, а заголовок раздела уезжает под неё. Браузер прокрутил блок к верхнему краю окна, но этот край закрыт шапкой.
Решение: задать отступ прокрутки. Подходят два свойства, результат у них одинаковый, разница в том, куда их ставить.
| Свойство | Куда ставить | Когда удобнее |
|---|---|---|
scroll-padding-top |
на html, один раз |
шапка одной высоты на всём сайте |
scroll-margin-top |
на целевой блок | отступ нужен только у части разделов или разный |
html {
scroll-behavior: smooth;
scroll-padding-top: 80px; /* высота шапки */
}
/* или точечно */
#price {
scroll-margin-top: 80px;
}
Если высота шапки меняется на мобильных, вынесите её в переменную и переопределите внутри медиа-запроса. Как писать такие условия под разные экраны, показано в статье про медиа-запросы в CSS. Описание свойства и примеры есть в справке MDN по scroll-margin-top.
Плавный скролл и настройка уменьшения анимации
У части людей анимация прокрутки вызывает дискомфорт, поэтому в Windows, macOS, iOS и Android есть настройка доступности, которая просит сайты убрать лишнее движение. CSS её видит через медиа-запрос prefers-reduced-motion.
Правильнее включать плавность только тем, кто такую настройку не трогал:
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}
Если настройка включена, этот код не применится, и якорь сработает мгновенно. Значения no-preference и reduce разобраны в справке MDN по prefers-reduced-motion.
Плавная прокрутка через JavaScript
CSS срабатывает на переходы по якорям и на прокрутку, которую запускает скрипт. Когда скроллить нужно по событию (кнопка возврата наверх, переход к ошибке в форме, автопрокрутка чата), используют методы DOM. Если с объектной моделью документа вы пока не знакомы, начните со статьи про DOM-дерево в JavaScript.
window.scrollTo и scrollIntoView
Оба метода принимают опцию behavior. Значение smooth включает анимацию, даже если в CSS ничего не задано:
// кнопка возврата наверх
document.querySelector('.to-top').addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// прокрутить к конкретному блоку
document.getElementById('price').scrollIntoView({ behavior: 'smooth', block: 'start' });
Саму кнопку удобнее делать тегом button, а не ссылкой: варианты разметки есть в инструкции как сделать кнопку в HTML. Полный список опций есть в справке MDN по window.scrollTo() и Element.scrollIntoView().
У behavior есть третье значение, auto. Оно стоит по умолчанию и берёт поведение из CSS: при html { scroll-behavior: smooth; } обычный scrollTo тоже станет плавным.
Свой скролл с заданной длительностью
Если нужна конкретная скорость, например ровно 600 мс, анимацию пишут сами через requestAnimationFrame:
function smoothScrollTo(targetY, duration) {
const startY = window.scrollY;
const distance = targetY - startY;
const startTime = performance.now();
const ease = t => (t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2);
function step(now) {
const progress = Math.min((now - startTime) / duration, 1);
window.scrollTo(0, startY + distance * ease(progress));
if (progress < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
smoothScrollTo(3100, 600);
Функция ease медленно разгоняет прокрутку и плавно тормозит у цели. Важная деталь: на html в этом случае не должно стоять scroll-behavior: smooth, иначе каждый промежуточный scrollTo браузер начнёт сглаживать сам, и анимации наложатся.
Такие функции на requestAnimationFrame пишет почти каждый JavaScript-разработчик. Если стрелочные функции и performance.now() пока читаются с трудом, базу языка дают курсы по JavaScript.
Плавная прокрутка колесом мыши
scroll-behavior не трогает прокрутку, которую делает сам человек колесом, тачпадом или клавишами. Эффект «вязкого» скролла, как на сайтах студий, делают библиотеки.
- Lenis ставится через
npm i lenis. По README сглаживание по умолчанию задаёт интерполяцияlerp(0,1), а длительностьdurationдействует, только еслиlerpне задан. Прокрутку к якорям включает опцияanchors. - Плагин ScrollSmoother из GSAP подойдёт тем, кто уже собирает анимации на этой библиотеке.
- Старый вариант на jQuery через
$('html, body').animate()до сих пор встречается в шаблонах, но для новых проектов хватает нативных методов из блока выше.
Подключать библиотеку ради одного якорного меню не стоит: это лишний код, который замедлит загрузку страницы.
Какой способ выбрать

| Задача | Способ |
|---|---|
| меню из якорных ссылок на лендинге | html { scroll-behavior: smooth; } |
| заголовок прячется под шапкой | scroll-padding-top или scroll-margin-top |
| прокрутка внутри блока | scroll-behavior на сам контейнер |
| кнопка возврата наверх, скролл по событию | scrollTo или scrollIntoView с behavior: 'smooth' |
| нужна своя длительность | функция на requestAnimationFrame |
| плавное колесо мыши | Lenis, GSAP ScrollSmoother |
Для сайта на Tailwind CSS отдельный код не нужен: класс scroll-smooth на теге html задаёт то же свойство, это описано в документации Tailwind.
Почему не работает плавный скролл
Большинство проблем сводится к пяти причинам.
- Свойство стоит на
body, а не наhtml. MDN прямо пишет, что сbodyоно на окно не переносится. Решение: перенести правило наhtmlили:root. - Прокручивается не страница, а обёртка. Если контент лежит в блоке с
overflow: autoи фиксированной высотой, крутится этот блок. Решение: поставитьscroll-behaviorна него. - В системе включено уменьшение анимации. Если вы обернули правило в
prefers-reduced-motion, у вас самих прокрутка будет мгновенной. Это не баг, проверьте настройку доступности. - Ссылка ведёт не туда.
href="#Price"иid="price"не совпадут, регистр букв важен. Скопируйтеidиз разметки, а не набирайте заново. - Скрипт перехватывает клик. Обработчик с
event.preventDefault()на ссылках отменяет обычный переход по якорю, и CSS уже не участвует.
Обратная ситуация тоже бывает. В одностраничном приложении после смены экрана страница медленно едет наверх, хотя должна сразу показаться сверху. Решение: вызвать window.scrollTo({ top: 0, behavior: 'instant' }), значение instant отменяет плавность из CSS.
Поддержка браузерами
Свойство поддерживают все современные браузеры. Последним поддержку добавил Safari: до версии 15.4 он scroll-behavior игнорировал, и якорь просто срабатывал рывком. Ничего не ломается, поэтому отдельный запасной вариант не нужен.
| Браузер | scroll-behavior |
scroll-margin-top |
|---|---|---|
| Chrome | с версии 61 | с версии 69 |
| Edge | с версии 79 | с версии 79 |
| Firefox | с версии 36 | с версии 68 |
| Safari | с версии 15.4 | с версии 14.1 |
Версии взяты из таблиц совместимости MDN, актуальный охват по странам удобно смотреть на Can I use. Сам механизм плавной прокрутки описан в спецификации CSSOM View.
Где освоить CSS системно
Плавный скролл решается одной строкой, но вокруг неё десятки похожих задач: сетки, адаптивность, анимации, доступность. Если вы хотите верстать без поиска каждого свойства, имеет смысл пройти курс по CSS с практикой на реальных макетах.
Посмотреть, чем занимается HTML-верстальщик и как стать фронтенд-разработчиком, можно в наших разборах профессий. Все программы по навыку собраны в каталоге курсов по CSS.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| HTML и CSS с нуля Перейти на сайт курса | 91 626 ₽ | 7635 ₽/мес. | 11 месяцев | Обзор курса | |
| HTML и CSS. Адаптивная вёрстка и автоматизация Перейти на сайт курса | 23 400 ₽ | 3900 ₽/мес. | 2 месяца | Обзор курса | |
| Основы вёрстки HTML и CSS Перейти на сайт курса | 32 676 ₽ | 2723 ₽/мес. | 3 месяца | Обзор курса | |
| HTML и CSS с нуля | 195 160 ₽ | 7972 ₽/мес. | 12 месяцев | Обзор курса | |
| Онлайн-курс Вёрстка на HTML и CSS Перейти на сайт курса | 29 900 ₽ | 2491 ₽/мес. | 3 месяца | Обзор курса |
Больше программ — в полном каталоге курсов по CSS




