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



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



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



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

871   4  

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 С полосой прокрутки уже вычитается. (Кроме того, Chrome отображает paddingBottom в нижней части содержимого прокрутки, а другие браузеры не делают)

Если вы хотите использовать ширину прокрутки, чтобы получить "Реал" ШИРИНА/ВЫСОТА СОДЕРЖИМОГО (поскольку содержимое может быть больше, чем CSS-определенная ширина / высота-Box)ширина прокрутки / Высота очень ненадежна поскольку некоторые браузеры, похоже," перемещают " 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

    • offsetWidth: 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)

    • clientWidth: 505 (chrome53, ff49, safari9)

    • clientWidth: 508 (edge13)
    • clientWidth: 503 (ie11)
    • clientHeight: 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)
  • раздел 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)
    • clientWidth: 475 (chrome53, ff49, safari9)
    • clientWidth: 478 (edge13)
    • clientWidth: 473 (ie11)
    • clientHeight: 290 (chrome53, ff49, safari9, edge13, ie11)

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

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

    • 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)
    • clientWidth: 505 (chrome53, ff49, safari9)
    • clientWidth: 508 (edge13)
    • clientWidth: 503 (ie11)
    • clientHeight: 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, результаты подтверждают, что теория, стоящая за этим, работает.

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

  • 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

Comments

    Ничего не найдено.