Размеры окна и прокрутка в JavaScript
Узнайте, как измерять viewport, читать размер документа, отслеживать позицию прокрутки и управлять ею программно в JavaScript.
Понимание размеров окна и поведения прокрутки необходимо для создания адаптивных веб-интерфейсов. В этой статье рассматривается, как измерить viewport (видимую область страницы), как получить полный размер документа, как узнать насколько страница прокручена и как управлять прокруткой программно — включая плавную прокрутку и прокрутку элемента в область видимости. Каждая концепция сопровождается запускаемым примером.
Ключевое различие, которое следует помнить: viewport — это то, что пользователь видит в данный момент, тогда как документ — это вся страница целиком, большая часть которой может быть скрыта за пределами экрана.
Измерение viewport (видимого окна)
Viewport — это прямоугольник страницы, который пользователь видит прямо сейчас. Существует два способа получить его размер, и разница между ними важна.
document.documentElement.clientWidth/clientHeight— ширина и высота viewport без учёта полосы прокрутки. Это правильный выбор, когда нужна реальная область, доступная для содержимого.window.innerWidth/innerHeight— весь внутренний размер окна включая ширину полосы прокрутки. Удобно для быстрых проверок, но может быть на несколько пикселей большеclientWidth, если полоса прокрутки присутствует.
Используйте clientWidth/clientHeight при расчётах макета (например, центрирование элемента); используйте innerWidth/innerHeight для проверок в стиле точек останова, где несколько пикселей не имеют значения.
// Viewport size excluding the scrollbar (recommended for layout)
console.log(document.documentElement.clientWidth);
console.log(document.documentElement.clientHeight);
// Window interior including the scrollbar
console.log(window.innerWidth);
console.log(window.innerHeight);Следующий пример отображает размер viewport в реальном времени и обновляется при изменении размеров окна.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Window Size Display</title>
</head>
<body>
<div id="window-info"></div>
<script>
function displayWindowSize() {
const w = document.documentElement.clientWidth;
const h = document.documentElement.clientHeight;
document.getElementById('window-info').innerHTML =
'Viewport width: ' + w + 'px<br>' +
'Viewport height: ' + h + 'px';
}
window.addEventListener('resize', displayWindowSize);
window.addEventListener('load', displayWindowSize);
</script>
</body>
</html>Измерение полного размера документа
Чтобы получить высоту всей страницы — включая часть, скрытую за пределами экрана, — нужно прочитать свойства scroll* элемента документа. Из-за исторических несоответствий между браузерами надёжный способ — взять максимальное значение из нескольких измерений:
const scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
console.log('Full document height: ' + scrollHeight);Это именно то значение, которое нужно для создания индикатора прогресса, триггера бесконечной прокрутки («достиг ли я конца страницы?») или кнопки «прокрутить вниз». scrollWidth работает аналогично для горизонтального переполнения.
Чтение текущей позиции прокрутки
Чтобы узнать, насколько страница прокручена, используйте:
window.scrollX— горизонтальное смещение прокрутки в пикселях (также называетсяwindow.pageXOffset— устаревший псевдоним).window.scrollY— вертикальное смещение прокрутки в пикселях (псевдонимwindow.pageYOffset).
scrollX/scrollY — современные названия; pageXOffset/pageYOffset идентичны им и по-прежнему поддерживаются для обратной совместимости.
console.log(window.scrollX); // same as window.pageXOffset
console.log(window.scrollY); // same as window.pageYOffsetПрограммное управление прокруткой
Объект window предоставляет три метода для самостоятельного перемещения по странице.
window.scrollTo(x, y)— прокручивает к абсолютной позиции.scrollTo(0, 0)возвращает к началу.window.scrollBy(dx, dy)— прокручивает относительно текущей позиции.scrollBy(0, 100)перемещает на 100px вниз от текущего места.element.scrollIntoView()— прокручивает страницу так, чтобы определённый элемент стал видимым.
Все три метода принимают объект параметров с behavior: 'smooth' для анимированной прокрутки вместо мгновенного перехода:
// Smoothly scroll back to the top of the page
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
// Nudge the page down by one viewport height
window.scrollBy({ top: window.innerHeight, behavior: 'smooth' });Плавная прокрутка к элементу
scrollIntoView — это простейший способ перейти к разделу, например, для кнопки «вернуться наверх» или «перейти к комментариям». Передача { behavior: 'smooth' } анимирует движение:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Smooth Scrolling</title>
</head>
<body>
<button onclick="document.getElementById('target').scrollIntoView({ behavior: 'smooth' });">Go to Target</button>
<div style="height: 2000px;">
<div id="target" style="margin-top: 1800px;">Target Element</div>
</div>
</body>
</html>Отслеживание позиции прокрутки
Создавайте динамические эффекты на основе позиции прокрутки пользователя. Пример ниже обновляет фиксированный элемент, отображая текущее вертикальное смещение прокрутки при каждом событии scroll.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Scroll Position Detector</title>
</head>
<body>
<div style="height: 3000px;">
<div style="position: fixed;">Scroll position: <span id="position">0</span>px</div>
</div>
<script>
const positionSpan = document.getElementById('position');
window.addEventListener('scroll', function() {
positionSpan.innerHTML = window.scrollY;
});
</script>
</body>
</html>Примечание: для более широкой поддержки браузеров можно использовать document.documentElement.scrollTop как запасной вариант для window.scrollY.
Получение позиции элемента с помощью getBoundingClientRect
element.getBoundingClientRect() возвращает размер элемента и его позицию относительно viewport (а не документа). Возвращаемый объект содержит поля top, bottom, left, right, width и height.
Поскольку значения указываются относительно viewport, они изменяются при прокрутке. Чтобы преобразовать позицию элемента в координаты документа, добавьте текущее смещение прокрутки:
const box = element.getBoundingClientRect();
// Distance from the top of the viewport (changes while scrolling)
console.log(box.top);
// Distance from the top of the whole document (stable)
const documentTop = box.top + window.scrollY;
console.log(documentTop);Распространённый вариант использования — проверка того, виден ли элемент на экране в данный момент:
function isInViewport(el) {
const r = el.getBoundingClientRect();
return r.top >= 0 &&
r.bottom <= document.documentElement.clientHeight;
}Для более детального изучения разницы между координатами viewport и документа смотрите Координаты в JavaScript.
Настройка полос прокрутки для улучшения внешнего вида
Кастомные полосы прокрутки могут улучшить визуальную привлекательность сайта:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Custom Scrollbars</title>
<style>
body {
height: 2000px; /* For demonstration */
}
/* Custom scrollbar styling */
::-webkit-scrollbar {
width: 12px;
}
::-webkit-scrollbar-track {
background: darkblue;
}
::-webkit-scrollbar-thumb {
background-color: lightgreen;
border-radius: 10px;
border: 3px solid darkcyan;
}
</style>
</head>
<body>
Scroll to see the custom scrollbar!
</body>
</html>В этом примере используются псевдоэлементы для выбора и стилизации различных частей полосы прокрутки. Вот описание каждого используемого CSS-свойства:
::-webkit-scrollbar: этот псевдоэлемент нацелен на саму полосу прокрутки. Мы установили ширину 12 пикселей, что определяет толщину полосы прокрутки.::-webkit-scrollbar-track: этот псевдоэлемент представляет дорожку (или канавку), по которой движется ползунок полосы прокрутки. Мы стилизовали её тёмно-синим фоном. Использованные цвета выбраны для наглядного отображения различий между частями полосы прокрутки. В реальных приложениях рекомендуется использовать более сдержанные цвета.::-webkit-scrollbar-thumb: этот псевдоэлемент нацелен на перетаскиваемую часть полосы прокрутки — ползунок. Мы выбрали светло-зелёный цвет для ползунка, чтобы он выделялся на фоне дорожки для лучшей видимости.border-radius: 10pxприменяет скруглённые углы к ползунку, придавая ему современный и аккуратный вид. Также используется рамка шириной 3 пикселя сплошного тёмно-бирюзового цвета.
Примечание: псевдоэлементы ::-webkit-scrollbar специфичны для браузеров на основе Chromium. Для Firefox и современных стандартов рассмотрите использование CSS-свойств scrollbar-width и scrollbar-color. Пример: scrollbar-width: thin; scrollbar-color: lightgreen darkblue;
Заключение
Освоив методы работы с размерами окна и прокруткой в JavaScript, вы сможете значительно улучшить пользовательский опыт и адаптивность своих веб-проектов. Помните ключевое различие: clientWidth/clientHeight измеряют видимый viewport, свойства scroll* измеряют полный документ, а scrollX/scrollY (они же pageXOffset/pageYOffset) показывают, насколько страница прокручена. Используйте scrollTo, scrollBy и scrollIntoView с behavior: 'smooth' для управления прокруткой страницы самостоятельно.
Для дальнейшего изучения:
- Прокрутка в JavaScript — события и паттерны реагирования на прокрутку.
- Координаты в JavaScript — системы координат viewport и документа в деталях.
- Работа со стилями в DOM — чтение и изменение стилей элементов, включая размеры, рассмотренные здесь.