分别了解offsetWidth,clientWidth,scrollWidth和-Height
有关StackOverflow关于offsetWidth / clientWidth / scrollWidth(和-Height,分别)的几个问题,但没有给出这些值是什么的全面解释。
此外,网上有几个来源给出混淆或不正确的信息。
你能给出一个完整的解释,包括一些视觉提示? 另外,如何使用这些值来计算滚动条宽度?
CSS框模型相当复杂,特别是在滚动内容时。 虽然浏览器使用CSS中的值来绘制框,但如果仅使用CSS,则使用JS确定所有的尺寸并不是直接的。
这就是为什么每个元素有六个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已经减less了滚动条的width
。 (另外,Chrome会将paddingBottom呈现到滚动内容的底部,而其他浏览器则不会)
如果你想使用scrollWidth获得“真实”的 内容宽度/高度 (因为内容可以比css定义的宽度/高度框大) scrollWidth /高度是非常不可靠的,因为一些浏览器似乎“移动”paddingRIGHT &paddingBOTTOM如果内容很大。 然后他们把垫子放在“太宽/高含量”的右边/底部(见下图)。
==>因此,要在某些浏览器中获得实际内容宽度,您必须从滚动宽度中减去两个填充,而在某些浏览器中,只需减去左填充即可。
我find了这个解决scheme,并希望添加这个作为评论,但不被允许。 所以我拍了这张照片,并且在“移动的填充”和“不可靠的scrollWidth”方面做了一些更清晰的处理。 在蓝色区域,您可以find我的解决scheme,以获取“真实”内容宽度!
希望这有助于使事情更清晰!
MDN上有一篇很好的文章解释了这些概念背后的理论: https : //developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
它还解释了boundingClientRect的宽度/高度与offsetWidth / offsetHeight之间的重要概念差异。
那么,为了certificate理论的正确与否,你需要一些testing。 这就是我在这里所做的: https : //github.com/lingtalfi/dimensions-cheatsheet
它正在testingchrome53,ff49,safari9,edge13和ie11。
testing的结果certificate了这个理论是正确的。 为了testing,我创build了3个div,每个包含10个lipsum段落。 一些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 / clientHeight:布局填充框的可见部分的尺寸(不包括滚动条)
- scrollWidth / scrollHeight:布局填充框的尺寸(如果不受滚动条的限制)
注意:在edge13中默认的垂直滚动条宽度是12px,在chrome53,ff49和safari9中是15px,在ie11中是17px(通过截图中的photoshop中的测量完成,并且由testing结果certificate是正确的)。
但是,在某些情况下,也许你的应用程序没有使用默认的垂直滚动条的宽度。
因此,给定这些概念的定义,垂直滚动条的宽度应该等于(在伪代码中):
-
布局尺寸:offsetWidth – clientWidth – (borderLeftWidth + borderRightWidth)
-
渲染尺寸:boundingClientRect.width – clientWidth – (borderLeftWidth + borderRightWidth)
请注意,如果您不明白布局与渲染,请阅读mdn文章。
另外,如果你有另一个浏览器(或者你想自己查看testing结果),你可以在这里看到我的testing页面: http : //codepen.io/lingtalfi/pen/BLdBdL
我创build了一个更全面和更清晰的版本,有些人可能会发现有用的记住哪个名称对应于哪个值。 我使用了Chrome开发工具的颜色代码,并且对称地组织标签以更快地提取类比:
-
注1:如果文本的方向被设置为从右到左(因为在这种情况下向左显示
clientLeft
还包括垂直滚动条的宽度, -
注2:最外面的线代表最近的定位父亲(
position
属性设置为不同于static
或initial
值的元素)。 因此,如果直接容器不是定位元素,则该行不代表层次结构中的第一个容器,而代表层次中较高的另一个元素。 如果找不到定位的父对象,浏览器将把html
或body
元素作为引用
希望有人发现它有用,只是我2美分;)