Понимание offsetWidth, clientWidth, scrollWidth и -Height соответственно
На StackOverflow можно встретить множество вопросов о свойствах offsetWidth, clientWidth и scrollWidth (также и о соответствующих -Height), но ни один из них не предлагает полного объяснения этих значений.
Кроме того, в интернете есть несколько источников, которые предоставляют запутанную или неверную информацию по этой теме.
Можете ли вы предоставить полное объяснение с наглядными примерами? Кроме того, как можно использовать эти значения для расчета ширины полосы прокрутки?
2 ответ(ов)
На MDN есть хорошая статья, которая объясняет теорию, стоящую за этими концепциями: CSS Object Model.
В статье подробно изложены важные концептуальные различия между шириной/высотой boundingClientRect и offsetWidth/offsetHeight.
Для проверки теории вам понадобятся тесты. Именно это я и сделал: GitHub репозиторий с тестами.
Тесты проводились в браузерах Chrome 53, Firefox 49, Safari 9, Edge 13 и IE 11.
Результаты тестов подтвердили, что теория в целом верна. Для тестов я создал три div, каждый из которых содержал по 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 (все браузеры)offsetHeight: 330 (все браузеры)bcr.width: 530 (все браузеры)bcr.height: 330 (все браузеры)clientWidth: 505 (Chrome, Firefox, Safari)clientWidth: 508 (Edge)clientWidth: 503 (IE)clientHeight: 320 (все браузеры)scrollWidth: 505 (Chrome, Safari, Firefox)scrollWidth: 508 (Edge)scrollWidth: 503 (IE)scrollHeight: 916 (Chrome, Safari)scrollHeight: 954 (Firefox)scrollHeight: 922 (Edge, IE)
div2
offsetWidth: 500 (все браузеры)offsetHeight: 300 (все браузеры)bcr.width: 500 (все браузеры)bcr.height: 300 (Chrome, Firefox, Safari)bcr.height: 299.9999694824219 (Edge, IE)clientWidth: 475 (Chrome, Firefox, Safari)clientWidth: 478 (Edge)clientWidth: 473 (IE)clientHeight: 290 (все браузеры)scrollWidth: 475 (Chrome, Safari, Firefox)scrollWidth: 478 (Edge)scrollWidth: 473 (IE)scrollHeight: 916 (Chrome, Safari)scrollHeight: 954 (Firefox)scrollHeight: 922 (Edge, IE)
div3
offsetWidth: 530 (все браузеры)offsetHeight: 330 (все браузеры)bcr.width: 265 (все браузеры)bcr.height: 165 (все браузеры)clientWidth: 505 (Chrome, Firefox, Safari)clientWidth: 508 (Edge)clientWidth: 503 (IE)clientHeight: 320 (все браузеры)scrollWidth: 505 (Chrome, Safari, Firefox)scrollWidth: 508 (Edge)scrollWidth: 503 (IE)scrollHeight: 916 (Chrome, Safari)scrollHeight: 954 (Firefox)scrollHeight: 922 (Edge, IE)
Таким образом, кроме значения высоты boundingClientRect (299.9999694824219 вместо ожидаемых 300) в Edge 13 и IE 11, результаты подтверждают правильность теории.
Вот как я определяю эти концепции:
offsetWidth/offsetHeight: размеры области границ макета.boundingClientRect: размеры области границ визуализации.clientWidth/clientHeight: размеры видимой части области границ макета (исключая полосы прокрутки).scrollWidth/scrollHeight: размеры области границ макета, если бы она не была ограничена полосами прокрутки.
Обратите внимание: ширина стандартной вертикальной полосы прокрутки составляет 12px в Edge 13, 15px в Chrome, Firefox и Safari, и 17px в IE 11 (это было измерено с помощью Photoshop на скриншотах и подтверждено результатами тестов).
Однако в некоторых случаях ваше приложение может не использовать ширину стандартной вертикальной полосы прокрутки.
Таким образом, согласно определениям этих концепций, ширина вертикальной полосы прокрутки должна быть равна (в псевдокоде):
- размер макета:
offsetWidth - clientWidth - (borderLeftWidth + borderRightWidth) - размер визуализации:
boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)
Если вам не совсем понятно, что такое макет и что такое визуализация, пожалуйста, прочитайте статью на MDN.
Также, если у вас есть другой браузер (или если вы хотите увидеть результаты тестов сами), вы можете посетить мою тестовую страницу здесь: CodePen.
Похоже, что ваш вопрос касается различных значений scrollWidth и scrollHeight, когда у элементов нет скроллбаров.
В ответах, которые вы видели, часто показывают скроллбары, однако scrollWidth может быть больше, чем clientWidth, даже если содержимое переполняет элемент без скроллбаров.
Рассмотрим следующий пример: <div style="width:1px">text</div>.
Здесь clientWidth будет равен 1, что обусловлено заданным CSS-стилем. В то же время scrollWidth составит 24, так как это связано с фактическим содержимым внутри элемента.
Таким образом, важно понимать, что scrollWidth и clientWidth могут выдавать различные значения независимо от наличия или отсутствия скроллбаров, и это связано с тем, как браузеры рассчитывают размеры элементов.
Получить координаты (X,Y) HTML-элемента
Проверка наличия класса у элемента в JavaScript
Как проверить, включён ли line-clamp?
Установить фиксированную ширину столбца таблицы независимо от количества текста в ячейках?
Как сделать перенос строки с помощью CSS, не используя <br />?