W3docs

Размеры окна и прокрутка в 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?
Was this page helpful?