Блочная модель CSS довольно сложна, особенно когда дело доходит до прокрутки контента. Хотя браузер использует значения из вашего CSS для рисования блоков, определить все измерения с помощью JS не так просто, если у вас есть только CSS.
Именно поэтому каждый элемент имеет шесть свойств DOM для вашего удобства: offsetWidth
, offsetHeight
, clientWidth
, clientHeight
, scrollWidth
и scrollHeight
. Это атрибуты только для чтения, представляющие текущий визуальный макет, и все они являются целыми числами (таким образом, возможно, подвержены ошибкам округления).
Давайте рассмотрим их подробно:
offsetWidth
, offsetHeight
: Размер визуального блока, включая все границы. Можно рассчитать, добавив width
/ height
и отступы и границы, если элемент имеетdisplay: block
clientWidth
, clientHeight
: Визуальная часть содержимого поля, не включая границы или полосы прокрутки, но содержит отступы. Не может быть рассчитан непосредственно из CSS, зависит от размера полосы прокрутки системы.
scrollWidth
, scrollHeight
: Размер всего содержимого блока, включая части, которые в данный момент скрыты за пределами области прокрутки. Не может быть рассчитан непосредственно из CSS, зависит от содержания.
Так offsetWidth
как ширина полосы прокрутки учитывается, мы можем использовать ее для вычисления ширины полосы прокрутки по формуле
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
К сожалению, мы можем получить ошибки округления, так offsetWidth
и clientWidth
всегда целые числа, в то время как фактические размеры могут быть дробными с другими , чем 1 уровнями масштабирования.
Обратите внимание, что это
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
ничего не работает надежно в Chrome, так как Chrome возвращается width
с скроллингом уже вычитали. (Кроме того, Chrome отображает paddingBottom внизу содержимого прокрутки, в то время как другие браузеры этого не делают)
element.getBoundingClientRect()
(см. Примечание на developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth )naturalWidth
иnaturalHeight
scrollHeight
включает,padding-bottom
ноscrollWidth
не включаетpadding-right
clientWidth
дляdocument.documentElement.clientWidth
отличается , как кажется, включают в себяpadding
,borders
иmargin
Я создал более полную и понятную версию, которую некоторые люди могут найти полезной для запоминания того, какое имя соответствует какому значению. Я использовал цветовой код Chrome Dev Tool и метки организованы симметрично, чтобы быстрее подобрать аналогии:
Примечание 1:
clientLeft
также включает ширину вертикальной полосы прокрутки, если направление текста установлено справа налево (поскольку в этом случае полоса отображается слева)Примечание 2: крайняя внешняя строка представляет ближайшего расположенного родителя (элемент, для
position
свойства которого установлено значение, отличное отstatic
илиinitial
). Таким образом, если прямой контейнер не является позиционированным элементом, то строка не представляет первый контейнер в иерархии, но другой элемент выше в иерархии. Если позиционированный родитель не найден, браузер примет элементhtml
или вbody
качестве ссылкиНадеюсь, кто-нибудь найдет это полезным, только мои 2 цента;)
источник
Если вы хотите использовать scrollWidth , чтобы получить «РЕАЛ» CONTENT ШИРИНА / ВЫСОТА (как содержание может быть больше , чем CSS определенная ширина / высота-Box) scrollWidth / Высота очень ненадежен , как какой - то браузер , кажется, «МАХ» на paddingRIGHT & paddingBOTTOM, если содержание слишком большое. Затем они помещают прокладки в ПРАВО / ВНИЗ «слишком широкого / высокого содержания» (см. Рисунок ниже).
==> Поэтому, чтобы получить РЕАЛЬНОЕ ШИРОКОЕ СОДЕРЖАНИЕ в некоторых браузерах, вы должны вычесть ОБА отступы из полосы прокрутки, а в некоторых браузерах вам нужно только вычесть ЛЕВЫЙ отступ.
Я нашел решение для этого и хотел добавить это как комментарий, но не позволили. Поэтому я сделал снимок и сделал его немного более понятным в отношении «перемещенных отступов» и «ненадежной ширины прокрутки». В СИНИЙ ОБЛАСТИ вы найдете мое решение о том, как получить «РЕАЛЬНУЮ» ШИРИНУ КОНТЕНТА!
Надеюсь, это поможет сделать вещи еще яснее!
источник
Есть хорошая статья о 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 div, содержащих по 10 абзацев lorem ipsum каждый. Некоторые CSS были применены к ним:
И вот результаты:
div1
высота: 330 (chrome53, ff49, safari9, edge13, ie11)
clientWidth: 505 (chrome53, ff49, safari9)
высота клиента: 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 505 (chrome53, safari9, ff49)
div2
clientHeight: 290 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 475 (chrome53, safari9, ff49)
div3
высота клиента: 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 505 (chrome53, safari9, ff49)
Таким образом, кроме значения высоты boundingClientRect (299.9999694824219 вместо ожидаемых 300) в edge13 и ie11, результаты подтверждают, что теория, стоящая за этим, работает.
Отсюда мое определение этих понятий:
Примечание. По умолчанию вертикальная полоса прокрутки имеет ширину 12 пикселей в edge13, 15 пикселей в chrome53, ff49 и safari9 и 17 пикселей в ie11 (сделано по измерениям в фотошопе из скриншотов и подтверждено результатами тестов).
Однако в некоторых случаях, возможно, ваше приложение не использует ширину вертикальной полосы прокрутки по умолчанию.
Таким образом, учитывая определения этих понятий, ширина вертикальной полосы прокрутки должна быть равна (в псевдокоде):
Размер макета: offsetWidth - clientWidth - (borderLeftWidth + borderRightWidth)
измерение рендеринга: boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)
Обратите внимание, если вы не понимаете, что такое макет и рендеринг, пожалуйста, прочтите статью mdn.
Кроме того, если у вас есть другой браузер (или если вы хотите увидеть результаты тестов для себя), вы можете увидеть мою тестовую страницу здесь: http://codepen.io/lingtalfi/pen/BLdBdL
источник