Javascript размер окна css

Размеры и прокрутка окна

Как узнать ширину и высоту окна браузера? Как получить полную ширину и высоту документа, включая прокрученную часть? Как прокрутить страницу с помощью JavaScript?

Для большинства таких запросов мы можем использовать корневой элемент документа document.documentElement , который соответствует тегу . Однако есть дополнительные методы и особенности, которые необходимо учитывать.

Ширина/высота окна

Чтобы получить ширину/высоту окна, можно взять свойства clientWidth/clientHeight из document.documentElement :

Например, эта кнопка показывает высоту вашего окна:

Браузеры также поддерживают свойства window.innerWidth/innerHeight . Вроде бы, похоже на то, что нам нужно. Почему же не использовать их?

Если есть полоса прокрутки, и она занимает какое-то место, то свойства clientWidth/clientHeight указывают на ширину/высоту документа без неё (за её вычетом). Иными словами, они возвращают высоту/ширину видимой части документа, доступной для содержимого.

А window.innerWidth/innerHeight включают в себя полосу прокрутки.

Если полоса прокрутки занимает некоторое место, то эти две строки выведут разные значения:

В большинстве случаев нам нужна доступная ширина окна: для рисования или позиционирования. Полоса прокрутки «отъедает» её часть. Поэтому следует использовать documentElement.clientHeight/Width .

Обратите внимание, что геометрические свойства верхнего уровня могут работать немного иначе, если в HTML нет . Возможны странности.

В современном HTML мы всегда должны указывать DOCTYPE .

Ширина/высота документа

Теоретически, т.к. корневым элементом документа является documentElement , и он включает в себя всё содержимое, мы можем получить полный размер документа как documentElement.scrollWidth/scrollHeight .

Но именно на этом элементе, для страницы в целом, эти свойства работают не так, как предполагается. В Chrome/Safari/Opera, если нет прокрутки, то documentElement.scrollHeight может быть даже меньше, чем documentElement.clientHeight ! С точки зрения элемента это невозможная ситуация.

Чтобы надёжно получить полную высоту документа, нам следует взять максимальное из этих свойств:

Почему? Лучше не спрашивайте. Эти несоответствия идут с древних времён. Глубокой логики здесь нет.

Получение текущей прокрутки

Обычные элементы хранят текущее состояние прокрутки в elem.scrollLeft/scrollTop .

Что же со страницей? В большинстве браузеров мы можем обратиться к documentElement.scrollLeft/Top , за исключением основанных на старом WebKit (Safari), где есть ошибка (5991), и там нужно использовать document.body вместо document.documentElement .

К счастью, нам совсем не обязательно запоминать эти особенности, потому что текущую прокрутку можно прочитать из свойств window.pageXOffset/pageYOffset :

Эти свойства доступны только для чтения.

Прокрутка: scrollTo, scrollBy, scrollIntoView

Для прокрутки страницы из JavaScript её DOM должен быть полностью построен.

Например, если мы попытаемся прокрутить страницу из скрипта в , это не сработает.

Обычные элементы можно прокручивать, изменяя scrollTop/scrollLeft .

Мы можем сделать то же самое для страницы в целом, используя document.documentElement.scrollTop/Left (кроме основанных на старом WebKit (Safari), где, как сказано выше, document.body.scrollTop/Left ).

Есть и другие способы, в которых подобных несовместимостей нет: специальные методы window.scrollBy(x,y) и window.scrollTo(pageX,pageY) .

Метод scrollBy(x,y) прокручивает страницу относительно её текущего положения. Например, scrollBy(0,10) прокручивает страницу на 10px вниз.

Кнопка ниже демонстрирует это:

Метод scrollTo(pageX,pageY) прокручивает страницу на абсолютные координаты (pageX,pageY) . То есть, чтобы левый-верхний угол видимой части страницы имел данные координаты относительно левого верхнего угла документа. Это всё равно, что поставить scrollLeft/scrollTop . Для прокрутки в самое начало мы можем использовать scrollTo(0,0) .

Эти методы одинаково работают для всех браузеров.

scrollIntoView

Для полноты картины давайте рассмотрим ещё один метод: elem.scrollIntoView(top).

Читайте также:  Японские шторы для узкого окна

Вызов elem.scrollIntoView(top) прокручивает страницу, чтобы elem оказался вверху. У него есть один аргумент:

  • если top=true (по умолчанию), то страница будет прокручена, чтобы elem появился в верхней части окна. Верхний край элемента совмещён с верхней частью окна.
  • если top=false , то страница будет прокручена, чтобы elem появился внизу. Нижний край элемента будет совмещён с нижним краем окна.

Кнопка ниже прокрутит страницу так, что она сама окажется вверху:

А следующая кнопка прокрутит страницу так, что она сама окажется внизу

Запретить прокрутку

Иногда нам нужно сделать документ «непрокручиваемым». Например, при показе большого диалогового окна над документом – чтобы посетитель мог прокручивать это окно, но не документ.

Чтобы запретить прокрутку страницы, достаточно установить document.body.style.overflow = «hidden» .

Первая кнопка останавливает прокрутку, вторая возобновляет её.

Аналогичным образом мы можем «заморозить» прокрутку для других элементов, а не только для document.body .

Недостатком этого способа является то, что сама полоса прокрутки исчезает. Если она занимала некоторую ширину, то теперь эта ширина освободится, и содержимое страницы расширится, текст «прыгнет», заняв освободившееся место.

Это выглядит немного странно, но это можно обойти, если сравнить clientWidth до и после остановки, и если clientWidth увеличится (значит полоса прокрутки исчезла), то добавить padding в document.body вместо полосы прокрутки, чтобы оставить ширину содержимого прежней.

Итого

Ширина/высота видимой части документа (ширина/высота области содержимого): document.documentElement.clientWidth/Height

Ширина/высота всего документа с прокрученной частью:

Источник

Размеры и прокрутка элементов

Существует множество JavaScript-свойств, которые позволяют считывать информацию об элементе: ширину, высоту и другие геометрические характеристики. В этой главе мы будем называть их «метрики».

Они часто требуются, когда нам нужно передвигать или позиционировать элементы с помощью JavaScript.

Простой пример

В качестве простого примера демонстрации свойств мы будем использовать следующий элемент:

У элемента есть рамка (border), внутренний отступ (padding) и прокрутка. Полный набор характеристик. Обратите внимание, тут нет внешних отступов (margin), потому что они не являются частью элемента, для них нет особых JavaScript-свойств.

Результат выглядит так:

В иллюстрации выше намеренно продемонстрирован самый сложный и полный случай, когда у элемента есть ещё и полоса прокрутки. Некоторые браузеры (не все) отбирают место для неё, забирая его у области, отведённой для содержимого (помечена как «content width» выше).

Таким образом, без учёта полосы прокрутки ширина области содержимого (content width) будет 300px , но если предположить, что ширина полосы прокрутки равна 16px (её точное значение зависит от устройства и браузера), тогда остаётся только 300 — 16 = 284px , и мы должны это учитывать. Вот почему примеры в этой главе даны с полосой прокрутки. Без неё некоторые вычисления будут проще.

Нижние внутренние отступы padding-bottom изображены пустыми на наших иллюстрациях, но если элемент содержит много текста, то он будет перекрывать padding-bottom , это нормально.

Метрики

Вот общая картина с геометрическими свойствами:

Значениями свойств являются числа, подразумевается, что они в пикселях.

Давайте начнём исследовать, начиная снаружи элемента.

offsetParent, offsetLeft/Top

Эти свойства редко используются, но так как они являются «самыми внешними» метриками, мы начнём с них.

В свойстве offsetParent находится предок элемента, который используется внутри браузера для вычисления координат при рендеринге.

То есть, ближайший предок, который удовлетворяет следующим условиям:

  1. Является CSS-позиционированным (CSS-свойство position равно absolute , relative , fixed или sticky ),
  2. или , , ,
  3. или .
  4. Свойства offsetLeft/offsetTop содержат координаты x/y относительно верхнего левого угла offsetParent .

    В примере ниже внутренний

    Существует несколько ситуаций, когда offsetParent равно null :

    1. Для скрытых элементов (с CSS-свойством display:none или когда его нет в документе).
    2. Для элементов и .
    3. Для элементов с position:fixed .

    offsetWidth/Height

    Теперь переходим к самому элементу.

    Эти два свойства – самые простые. Они содержат «внешнюю» ширину/высоту элемента, то есть его полный размер, включая рамки.

    Для нашего элемента:

    • offsetWidth = 390 – внешняя ширина блока, её можно получить сложением CSS-ширины ( 300px ), внутренних отступов ( 2 * 20px ) и рамок ( 2 * 25px ).
    • offsetHeight = 290 – внешняя высота блока.

    Координаты и размеры в JavaScript устанавливаются только для видимых элементов.

    Если элемент (или любой его родитель) имеет display:none или отсутствует в документе, то все его метрики равны нулю (или null , если это offsetParent ).

    Например, свойство offsetParent равно null , а offsetWidth и offsetHeight равны 0 , когда мы создали элемент, но ещё не вставили его в документ, или если у элемента (или у его родителя) display:none .

    Мы можем использовать это, чтобы делать проверку на видимость:

    Заметим, что функция isHidden также вернёт true для элементов, которые в принципе показываются, но их размеры равны нулю (например, пустые

    clientTop/Left

    Пойдём дальше. Внутри элемента у нас рамки (border).

    Для них есть свойства-метрики clientTop и clientLeft .

    В нашем примере:

    • clientLeft = 25 – ширина левой рамки
    • clientTop = 25 – ширина верхней рамки

    …Но на самом деле эти свойства – вовсе не ширины рамок, а отступы внутренней части элемента от внешней.

    В чём же разница?

    Она возникает, когда документ располагается справа налево (операционная система на арабском языке или иврите). Полоса прокрутки в этом случае находится слева, и тогда свойство clientLeft включает в себя ещё и ширину полосы прокрутки.

    В этом случае clientLeft будет равно 25 , но с прокруткой – 25 + 16 = 41 .

    Вот соответствующий пример на иврите:

    clientWidth/Height

    Эти свойства – размер области внутри рамок элемента.

    Они включают в себя ширину области содержимого вместе с внутренними отступами padding , но без прокрутки:

    На рисунке выше посмотрим вначале на высоту clientHeight .

    Горизонтальной прокрутки нет, так что это в точности то, что внутри рамок: CSS-высота 200px плюс верхние и нижние внутренние отступы ( 2 * 20px ), итого 240px .

    Теперь clientWidth – ширина содержимого здесь равна не 300px , а 284px , т.к. 16px отведено для полосы прокрутки. Таким образом: 284px плюс левый и правый отступы – всего 324px .

    Если нет внутренних отступов padding , то clientWidth/Height в точности равны размеру области содержимого внутри рамок и полосы прокрутки (если она есть).

    Поэтому в тех случаях, когда мы точно знаем, что отступов нет, можно использовать clientWidth/clientHeight для получения размеров внутренней области содержимого.

    scrollWidth/Height

    Эти свойства – как clientWidth/clientHeight , но также включают в себя прокрученную (которую не видно) часть элемента.

    На рисунке выше:

    • scrollHeight = 723 – полная внутренняя высота, включая прокрученную область.
    • scrollWidth = 324 – полная внутренняя ширина, в данном случае прокрутки нет, поэтому она равна clientWidth .

    Эти свойства можно использовать, чтобы «распахнуть» элемент на всю ширину/высоту.

    Нажмите на кнопку, чтобы распахнуть элемент:

    scrollLeft/scrollTop

    Свойства scrollLeft/scrollTop – ширина/высота невидимой, прокрученной в данный момент, части элемента слева и сверху.

    Следующая иллюстрация показывает значения scrollHeight и scrollTop для блока с вертикальной прокруткой.

    Другими словами, свойство scrollTop – это «сколько уже прокручено вверх».

    В отличие от большинства свойств, которые доступны только для чтения, значения scrollLeft/scrollTop можно изменять, и браузер выполнит прокрутку элемента.

    При клике на следующий элемент будет выполняться код elem.scrollTop += 10 . Поэтому он будет прокручиваться на 10px вниз.

    Установка значения scrollTop на 0 или Infinity прокрутит элемент в самый верх/низ соответственно.

    Не стоит брать width/height из CSS

    Мы рассмотрели метрики, которые есть у DOM-элементов, и которые можно использовать для получения различных высот, ширин и прочих расстояний.

    Но как мы знаем из главы Стили и классы, CSS-высоту и ширину можно извлечь, используя getComputedStyle .

    Так почему бы не получать, к примеру, ширину элемента при помощи getComputedStyle , вот так?

    Почему мы должны использовать свойства-метрики вместо этого? На то есть две причины:

    Во-первых, CSS-свойства width/height зависят от другого свойства – box-sizing , которое определяет, «что такое», собственно, эти CSS-ширина и высота. Получается, что изменение box-sizing , к примеру, для более удобной вёрстки, сломает такой JavaScript.

    Во-вторых, в CSS свойства width/height могут быть равны auto , например, для инлайнового элемента:

    Конечно, с точки зрения CSS width:auto – совершенно нормально, но нам-то в JavaScript нужен конкретный размер в px , который мы могли бы использовать для вычислений. Получается, что в данном случае ширина из CSS вообще бесполезна.

    Есть и ещё одна причина: полоса прокрутки. Бывает, без полосы прокрутки код работает прекрасно, но стоит ей появиться, как начинают проявляться баги. Так происходит потому, что полоса прокрутки «отъедает» место от области внутреннего содержимого в некоторых браузерах. Таким образом, реальная ширина содержимого меньше CSS-ширины. Как раз это и учитывают свойства clientWidth/clientHeight .

    …Но с getComputedStyle(elem).width ситуация иная. Некоторые браузеры (например, Chrome) возвращают реальную внутреннюю ширину с вычетом ширины полосы прокрутки, а некоторые (например, Firefox) – именно CSS-свойство (игнорируя полосу прокрутки). Эти кроссбраузерные отличия – ещё один повод не использовать getComputedStyle , а использовать свойства-метрики.

    Если ваш браузер показывает полосу прокрутки (например, под Windows почти все браузеры так делают), то вы можете протестировать это сами, нажав на кнопку в ифрейме ниже.

    У элемента с текстом в стилях указано CSS-свойство width:300px .

    На ОС Windows браузеры Firefox, Chrome и Edge резервируют место для полосы прокрутки. Но Firefox отображает 300px , в то время как Chrome и Edge – меньше. Это из-за того, что Firefox возвращает именно CSS-ширину, а остальные браузеры – «реальную» ширину за вычетом прокрутки.

    Обратите внимание: описанные различия касаются только чтения свойства getComputedStyle(. ).width из JavaScript, визуальное отображение корректно в обоих случаях.

    Итого

    У элементов есть следующие геометрические свойства (метрики):

    • offsetParent – ближайший CSS-позиционированный родитель или ближайший td , th , table , body .
    • offsetLeft/offsetTop – позиция в пикселях верхнего левого угла относительно offsetParent .
    • offsetWidth/offsetHeight – «внешняя» ширина/высота элемента, включая рамки.
    • clientLeft/clientTop – расстояние от верхнего левого внешнего угла до внутренного. Для операционных систем с ориентацией слева-направо эти свойства равны ширинам левой/верхней рамки. Если язык ОС таков, что ориентация справа налево, так что вертикальная полоса прокрутки находится не справа, а слева, то clientLeft включает в своё значение её ширину.
    • clientWidth/clientHeight – ширина/высота содержимого вместе с внутренними отступами padding , но без полосы прокрутки.
    • scrollWidth/scrollHeight – ширины/высота содержимого, аналогично clientWidth/Height , но учитывают прокрученную, невидимую область элемента.
    • scrollLeft/scrollTop – ширина/высота прокрученной сверху части элемента, считается от верхнего левого угла.

    Все свойства доступны только для чтения, кроме scrollLeft/scrollTop , изменение которых заставляет браузер прокручивать элемент.

    Задачи

    Найти размер прокрутки снизу

    Свойство elem.scrollTop содержит размер прокрученной области при отсчёте сверху. А как подсчитать размер прокрутки снизу (назовём его scrollBottom )?

    Напишите соответствующее выражение для произвольного элемента elem .

    P.S. Проверьте: если прокрутки нет вообще или элемент полностью прокручен – оно должно давать 0 .

    Другими словами: (вся высота) минус (часть, прокрученная сверху) минус (видимая часть) – результат в точности соответствует размеру прокрутки снизу.

    Источник