Как на JavaScript реализовать плавную прокрутку (smooth scroll) к определенному элементу на странице без библиотек?
Плавная прокрутка (smooth scroll) — популярная UX-техника, позволяющая анимированно перемещаться к нужному элементу на странице. Существует несколько способов реализовать её на чистом JavaScript.
## Способ 1: scrollIntoView с опцией behavior
Самый простой и современный подход — использовать встроенный метод `scrollIntoView`:
javascript
const element = document.getElementById(‘target’);
element.scrollIntoView({ behavior: ‘smooth’, block: ‘start’ });
Параметр `behavior: ‘smooth’` включает плавную анимацию. Параметр `block` определяет выравнивание: `’start’`, `’center’`, `’end’` или `’nearest’`. Этот метод поддерживается всеми современными браузерами.
## Способ 2: window.scrollTo с поведением smooth
Если нужно прокрутить к конкретной позиции:
javascript
const element = document.getElementById(‘target’);
const offsetTop = element.getBoundingClientRect().top + window.pageYOffset;
window.scrollTo({
top: offsetTop,
behavior: ‘smooth’
});
Метод `getBoundingClientRect().top` возвращает позицию элемента относительно viewport, а `window.pageYOffset` добавляет текущую позицию прокрутки.
## Способ 3: Ручная анимация через requestAnimationFrame
Для максимального контроля над анимацией (например, кастомный easing) используют `requestAnimationFrame`:
javascript
function smoothScrollTo(targetY, duration) {
const startY = window.pageYOffset;
const distance = targetY — startY;
let startTime = null;
function animation(currentTime) {
if (!startTime) startTime = currentTime;
const elapsed = currentTime — startTime;
const progress = Math.min(elapsed / duration, 1);
const ease = progress < 0.5
? 2 * progress * progress
: -1 + (4 — 2 * progress) * progress;
window.scrollTo(0, startY + distance * ease);
if (elapsed {
link.addEventListener(‘click’, function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute(‘href’));
if (target) {
target.scrollIntoView({ behavior: ‘smooth’ });
}
});
});
## Учёт фиксированного хедера
Если на странице есть фиксированный header, нужно учесть его высоту:
javascript
const headerHeight = document.querySelector(‘header’).offsetHeight;
const targetPosition = element.getBoundingClientRect().top + window.pageYOffset — headerHeight;
window.scrollTo({ top: targetPosition, behavior: ‘smooth’ });
## Рекомендации
— Для большинства проектов достаточно `scrollIntoView({ behavior: ‘smooth’ })`.
— Если нужна поддержка старых браузеров — используйте `requestAnimationFrame`.
— Всегда учитывайте фиксированные элементы интерфейса при расчёте смещения.
— Не злоупотребляйте прокруткой — она должна улучшать UX, а не мешать пользователю.
