在StackOverflow上有几个关于offsetWidth / clientWidth / scrollWidth(和-Height)的问题,但没有一个给出这些值的全面解释。
此外,网络上也有一些来源提供令人困惑或不正确的信息。
你能给出一个完整的解释,包括一些视觉提示吗? 此外,如何使用这些值来计算滚动条宽度?
在StackOverflow上有几个关于offsetWidth / clientWidth / scrollWidth(和-Height)的问题,但没有一个给出这些值的全面解释。
此外,网络上也有一些来源提供令人困惑或不正确的信息。
你能给出一个完整的解释,包括一些视觉提示吗? 此外,如何使用这些值来计算滚动条宽度?
当前回答
我创建了一个更全面和更清晰的版本,有些人可能会发现它有助于记住哪个名称对应哪个值。我使用Chrome Dev Tool的颜色代码和标签是对称组织的,以更快地拾取类比:
Note 1: clientLeft also includes the width of the vertical scroll bar if the direction of the text is set to right-to-left (since the bar is displayed to the left in that case) Note 2: the outermost line represents the closest positioned parent (an element whose position property is set to a value different than static or initial). Thus, if the direct container isn’t a positioned element, then the line doesn’t represent the first container in the hierarchy but another element higher in the hierarchy. If no positioned parent is found, the browser will take the html or body element as reference
希望有人觉得它有用,只是我的2美分;)
其他回答
如果你想使用scrollWidth来获得“真实”的内容宽度/高度(因为内容可以比css定义的宽度/高度- box更大),scrollWidth/高度是非常不可靠的,因为一些浏览器似乎“移动”paddingRIGHT和paddingBOTTOM如果内容太大。然后,他们将填充放置在“太宽/高内容”的右侧/底部(见下图)。
因此,在一些浏览器中,你必须从scrollwidth中减去两个填充,而在一些浏览器中,你只需要减去LEFT填充。
我为此找到了一个解决方案,并想将其作为评论添加,但不被允许。所以我拍了这张照片,让它在“移动填充”和“不可靠的scrollWidth”方面更清楚一些。在蓝色区域,你可以找到我的解决方案,如何获得“真正的”内容宽度!
希望这有助于使事情更清楚!
CSS框模型相当复杂,特别是涉及滚动内容时。虽然浏览器使用CSS中的值来绘制方框,但如果只有CSS,则使用JS确定所有尺寸并不简单。
这就是为什么为了方便起见,每个元素都有六个DOM属性:offsetWidth, offsetHeight, clientWidth, clienttheight, scrollWidth和scrollHeight。这些是表示当前可视布局的只读属性,并且它们都是整数(因此可能会出现舍入错误)。
让我们来详细介绍一下:
offsetWidth, offsetHeight: The size of the visual box incuding all borders. Can be calculated by adding width/height and paddings and borders, if the element has display: block clientWidth, clientHeight: The visual portion of the box content, not including borders or scroll bars , but includes padding . Can not be calculated directly from CSS, depends on the system's scroll bar size. scrollWidth, scrollHeight: The size of all of the box's content, including the parts that are currently hidden outside the scrolling area. Can not be calculated directly from CSS, depends on the content.
试试它:jsFiddle
由于offsetWidth考虑了滚动条宽度,我们可以使用它通过公式计算滚动条宽度
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
不幸的是,我们可能会得到舍入错误,因为offsetWidth和clientWidth总是整数,而实际大小可能是小数,缩放级别可能不是1。
注意这一点
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
不可靠的工作在Chrome,因为Chrome返回宽度与滚动条已经减去。(此外,Chrome渲染paddingBottom滚动内容的底部,而其他浏览器没有)
MDN上有一篇很好的文章解释了这些概念背后的理论: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
它还解释了boundingClientRect的width/height与offsetWidth/offsetHeight之间的重要概念差异。
然后,为了证明这个理论是对是错,你需要一些测试。 这就是我在这里所做的:https://github.com/lingtalfi/dimensions-cheatsheet
它正在测试chrome53, ff49, safari9, edge13和ie11。
试验结果证明该理论大体上是正确的。 对于测试,我创建了3个div,每个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 (chrome53, ff49, safari9, edge13, ie11) offsetHeight: 330 (chrome53, ff49, safari9, edge13, ie11) bcr.width: 530 (chrome53, ff49, safari9, edge13, ie11) bcr.height: 330 (chrome53, ff49, safari9, edge13, ie11) clientWidth: 505 (chrome53, ff49, safari9) clientWidth: 508 (edge13) clientWidth: 503 (ie11) clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11) scrollWidth: 505 (chrome53, safari9, ff49) scrollWidth: 508 (edge13) scrollWidth: 503 (ie11) scrollHeight: 916 (chrome53, safari9) scrollHeight: 954 (ff49) scrollHeight: 922 (edge13, ie11) div2 offsetWidth: 500 (chrome53, ff49, safari9, edge13, ie11) offsetHeight: 300 (chrome53, ff49, safari9, edge13, ie11) bcr.width: 500 (chrome53, ff49, safari9, edge13, ie11) bcr.height: 300 (chrome53, ff49, safari9) bcr.height: 299.9999694824219 (edge13, ie11) clientWidth: 475 (chrome53, ff49, safari9) clientWidth: 478 (edge13) clientWidth: 473 (ie11) clientHeight: 290 (chrome53, ff49, safari9, edge13, ie11) scrollWidth: 475 (chrome53, safari9, ff49) scrollWidth: 478 (edge13) scrollWidth: 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.width: 265 (chrome53, ff49, safari9, edge13, ie11) bcr.height: 165 (chrome53, ff49, safari9, edge13, ie11) clientWidth: 505 (chrome53, ff49, safari9) clientWidth: 508 (edge13) clientWidth: 503 (ie11) clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11) scrollWidth: 505 (chrome53, safari9, ff49) scrollWidth: 508 (edge13) scrollWidth: 503 (ie11) scrollHeight: 916 (chrome53, safari9) scrollHeight: 954 (ff49) scrollHeight: 922 (edge13, ie11)
因此,除了edge13和ie11中boundingClientRect的高度值(299.9999694824219而不是预期的300),结果证实了这背后的理论是可行的。
下面是我对这些概念的定义:
offsetWidth/offsetHeight:布局边框框的尺寸 boundingClientRect:渲染边框框的尺寸 clientWidth/ clienttheight:布局填充框可见部分的尺寸(不包括滚动条) scrollWidth/scrollHeight:布局填充框的尺寸,如果它没有受到滚动条的限制
注意:默认的垂直滚动条宽度在edge13中是12px,在chrome53, ff49和safari9中是15px,在ie11中是17px(在photoshop中从截图测量,并被测试结果证明是正确的)。
然而,在某些情况下,也许你的应用程序没有使用默认的垂直滚动条的宽度。
因此,根据这些概念的定义,垂直滚动条的宽度应该等于(在伪代码中):
布局尺寸:offsetWidth - clientWidth - (borderLeftWidth + borderrighttwidth) 渲染维度:boundingClientRect。width - clientWidth - (borderLeftWidth + borderrighttwidth)
注意,如果你不理解布局和渲染,请阅读mdn文章。
另外,如果您有其他浏览器(或者您想自己查看测试结果),可以在这里看到我的测试页面:http://codepen.io/lingtalfi/pen/BLdBdL
我创建了一个更全面和更清晰的版本,有些人可能会发现它有助于记住哪个名称对应哪个值。我使用Chrome Dev Tool的颜色代码和标签是对称组织的,以更快地拾取类比:
Note 1: clientLeft also includes the width of the vertical scroll bar if the direction of the text is set to right-to-left (since the bar is displayed to the left in that case) Note 2: the outermost line represents the closest positioned parent (an element whose position property is set to a value different than static or initial). Thus, if the direct container isn’t a positioned element, then the line doesn’t represent the first container in the hierarchy but another element higher in the hierarchy. If no positioned parent is found, the browser will take the html or body element as reference
希望有人觉得它有用,只是我的2美分;)
客户端宽度/高度和偏移宽度/高度计算-使用示例CSS样式的快速总结:
裁判:https://javascript.info/size-and-scroll