Понимание 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, зависит от содержания.
попробуйте: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, если контент большой. Затем они помещают прокладки справа / внизу "слишком широкое / высокое содержание" (см. рисунок ниже).
==> поэтому, чтобы получить реальный контент Ширина в некоторых браузерах вам нужно вычитать оба отступа из ширины прокрутки, а в некоторых браузерах вам нужно вычесть только левый отступ.
Я нашел решение для этого и хотел добавить это в качестве комментария, но не разрешили. Поэтому я сделал снимок и сделал его немного яснее в отношении "перемещенных прокладок"и" ненадежной ширины прокрутки". в синей области вы найдете мое решение о том, как получить "реальную" ширину контента!
надеюсь, это поможет сделать вещи еще яснее!
Я создал более полную и чистую версию, которую некоторые люди могут найти полезной для запоминания, какое имя соответствует какому значению. Я использовал цветовой код Chrome Dev Tool и метки организованы симметрично, чтобы быстрее подобрать аналогии:
Примечание 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