Понимание offsetWidth, clientWidth, scrollWidth и-Height соответственно

есть несколько вопросов о StackOverflow относительно offsetWidth/clientWidth/scrollWidth (и-Height, соответственно), но ни один не дает исчерпывающего объяснения того, что это за значения.

кроме того, есть несколько источников в интернете, давая заблуждение или неверную информацию.

можете ли вы дать полное объяснение, включая некоторые визуальные подсказки? Кроме того, как эти значения можно использовать для расчета ширины полосы прокрутки?

4 ответов


модель CSS box довольно сложна, особенно когда дело доходит до прокрутки контента. Хотя браузер использует значения из вашего CSS для рисования полей, определение всех измерений с помощью JS не является прямым, если у вас есть только CSS.

вот почему каждый элемент имеет шесть свойств DOM для вашего удобства:offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidth и scrollHeight. Это атрибуты только для чтения, представляющие текущий визуальный макет, и все они чисел (таким образом, возможно, возможны ошибки округления).

давайте рассмотрим их подробно:

  • offsetWidth, offsetHeight: размер визуального поля, включающего все границы. Можно рассчитать, добавив width/height и отступы и границы, если элемент display: block
  • clientWidth, clientHeight: визуальная часть содержимого коробки, не включая границы или полосы прокрутки, но включает заполнение . Невозможно вычислить напрямую от CSS зависит размер полосы прокрутки системы.
  • scrollWidth, scrollHeight: размер всего содержимого коробки, включая части, которые в настоящее время скрыты за пределами области прокрутки. Не может быть рассчитан непосредственно из CSS, зависит от содержания.

CSS2 Box Model

попробуйте:jsFiddle


С offsetWidth учитывает ширину полосы прокрутки, мы можем использовать ее для расчета ширина полосы прокрутки по формуле

scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth

к сожалению, мы можем получить ошибки округления, поскольку offsetWidth и clientWidth всегда целые числа, в то время как фактические размеры могут быть дробными с уровнями масштабирования, отличными от 1.

обратите внимание, что это

scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth

тут не надежно работать в Chrome, так как Chrome возвращает width С scrollbar уже вычтены. (Кроме того, Chrome отображает paddingBottom в нижней части содержимого прокрутки, в то время как другие браузеры не)


Если вы хотите использовать scrollWidth для получения "Реал" ШИРИНА/ВЫСОТА СОДЕРЖИМОГО (поскольку содержимое может быть больше, чем заданная css ширина / высота)ширина прокрутки / Высота очень ненадежна поскольку некоторые браузеры, похоже," перемещают " paddingRIGHT & paddingBOTTOM, если контент большой. Затем они помещают прокладки справа / внизу "слишком широкое / высокое содержание" (см. рисунок ниже).

==> поэтому, чтобы получить реальный контент Ширина в некоторых браузерах вам нужно вычитать оба отступа из ширины прокрутки, а в некоторых браузерах вам нужно вычесть только левый отступ.

Я нашел решение для этого и хотел добавить это в качестве комментария, но не разрешили. Поэтому я сделал снимок и сделал его немного яснее в отношении "перемещенных прокладок"и" ненадежной ширины прокрутки". в синей области вы найдете мое решение о том, как получить "реальную" ширину контента!

надеюсь, это поможет сделать вещи еще яснее!

enter image description here


Я создал более полную и чистую версию, которую некоторые люди могут найти полезной для запоминания, какое имя соответствует какому значению. Я использовал цветовой код Chrome Dev Tool и метки организованы симметрично, чтобы быстрее подобрать аналогии:

enter image description here

  • Примечание 1: clientLeft также включает ширину вертикальной прокрутки если направление текста справа-налево (с панель отображается слева в тот случай)

  • примечание 2: самая внешняя строка представляет ближайший расположенный родитель (элемент,position свойству присваивается значение, отличное от static или initial). Таким образом, если прямой контейнер не расположенный элемент, то строка не представляет первый контейнер в иерархии, но другой элемент выше в иерархии. Если нет расположенный найден родитель, браузер примет html или body элемент в качестве ссылки


надеюсь, кто-то найдет это полезным, только мои 2 цента;)


есть хорошая статья о MDN, которая объясняет теорию этих понятий: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

это также объясняет важные концептуальные различия между шириной/высотой boundingClientRect и offsetWidth / offsetHeight.

затем, чтобы доказать правильность или неправильность теории, вам нужны некоторые тесты. Вот что я сделал здесь: https://github.com/lingtalfi/dimensions-cheatsheet

это тестирование для chrome53, ff49, safari9, edge13 и ie11.

результаты тестов доказывают, что теория в целом правильно. Для тестов я создал 3 divs, содержащих по 10 пунктов lorem ipsum каждый. К ним был применен css:

.div1{
    width: 500px;
    height: 300px;
    padding: 10px;
    border: 5px solid black;
    overflow: auto;
}
.div2{
    width: 500px;
    height: 300px;
    padding: 10px;
    border: 5px solid black;
    box-sizing: border-box;
    overflow: auto;
}

.div3{
    width: 500px;
    height: 300px;
    padding: 10px;
    border: 5px solid black;
    overflow: auto;
    transform: scale(0.5);
}

и вот результаты:

  • div1

    • ширина смещения: 530 (chrome53, ff49, safari9, edge13, ie11)
    • offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.ширина: 530 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.высота: 330 (chrome53, ff49, safari9, edge13, ie11)

    • ширина клиента: 505 (chrome53, ff49, safari9)

    • значения свойств clientwidth: 508 (edge13)
    • значения свойств clientwidth: 503 (ие11)
    • высота клиента: 320 (chrome53, ff49, safari9, edge13, ие11)

    • ширина прокрутки: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (edge13)
    • ширина прокрутки: 503 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, ie11)
  • раздел 2

    • offsetWidth: 500 (chrome53, ff49, safari9, edge13, ie11)
    • offsetHeight: 300 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.ширина: 500 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.высота: 300 (chrome53, ff49, safari9)
    • bcr.высота: 299.9999694824219 (edge13, ie11)
    • ширина клиента: 475 (chrome53, ff49, safari9)
    • значения свойств clientwidth: 478 (edge13)
    • значения свойств clientwidth: 473 (ие11)
    • высота клиента: 290 (chrome53, ff49, safari9, edge13, ие11)

    • ширина прокрутки: 475 (chrome53, safari9, ff49)

    • scrollWidth: 478 (edge13)
    • ширина прокрутки: 473 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, ie11)
  • див3

    • offsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
    • offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.ширина: 265 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.высота: 165 (chrome53, ff49, safari9, edge13, ie11)
    • ширина клиента: 505 (chrome53, ff49, safari9)
    • значения свойств clientwidth: 508 (edge13)
    • значения свойств clientwidth: 503 (ие11)
    • высота клиента: 320 (chrome53, ff49, safari9, edge13, ie11)

    • ширина прокрутки: 505 (chrome53, safari9, ff49)

    • scrollWidth: 508 (edge13)
    • ширина прокрутки: 503 (ie11)
    • scrollHeight: 916 (chrome53, safari9)
    • scrollHeight: 954 (ff49)
    • scrollHeight: 922 (edge13, ie11)

таким образом, помимо значения высоты boundingClientRect (299.9999694824219 вместо ожидаемых 300) в edge13 и ie11, результаты подтверждают, что теория, стоящая за этим, работает.

оттуда, вот мое определение этих понятий:--4-->

  • offsetWidth/offsetHeight: размеры поля границы макета
  • boundingClientRect: размеры поля границы отрисовки
  • clientWidth/clientHeight: размеры видимой части окна заполнения макета (за исключением полос прокрутки)
  • scrollWidth/scrollHeight: размеры окна заполнения макета, если он не был ограничен полосами прокрутки

примечание: по умолчанию ширина вертикальной полосы прокрутки-12px в edge13, 15px в chrome53, ff49 и safari9 и 17px в ie11 (сделано измерениями в photoshop со скриншотов и доказано по результатам тестов).

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

Так, даны определения этих понятий, ширина вертикальной полосы прокрутки должна быть равна (в псевдо-код):

  • размер макета: offsetWidth-clientWidth - (borderLeftWidth + borderRightWidth)

  • измерение отрисовки: boundingClientRect.width-clientWidth - (borderLeftWidth + borderRightWidth)

Примечание, Если вы не понимаете макет против рендеринга, пожалуйста, прочитайте статью mdn.

также, если у вас есть другой браузер (или если вы хотите увидеть результаты тестов на себе), вы можете увидеть мою тестовую страницу здесь: http://codepen.io/lingtalfi/pen/BLdBdL