StackOverflow上有几个关于offsetWidth / clientWidth / scrollWidth(和-Height)的问题,但没有一个问题可以全面解释这些值是什么 .
此外,网上有几个来源,提供令人困惑或不正确的信息 .
你能给出一个完整的解释,包括一些视觉提示吗?另外,如何使用这些值来计算滚动条宽度?
CSS框模型相当复杂,特别是在滚动内容时 . 虽然浏览器使用CSS中的值来绘制框,但如果只有CSS,则使用JS确定所有维度并不是直截了当的 .
这就是为什么每个元素都有六个DOM属性以方便您使用: offsetWidth , offsetHeight , clientWidth , clientHeight , scrollWidth 和 scrollHeight . 这些是表示当前可视布局的只读属性,并且它们都是整数(因此可能会出现舍入错误) .
offsetWidth
offsetHeight
clientWidth
clientHeight
scrollWidth
scrollHeight
让我们详细介绍一下:
offsetWidth , offsetHeight :包含所有边框的视觉框的大小 . 可以通过添加 width / height 和填充和边框来计算,如果元素有 display: block
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
not 在Chrome中可靠地运行,因为Chrome返回 width ,滚动条已经减去 . (另外,Chrome会将paddingBottom渲染到滚动内容的底部,而其他浏览器则不会)
我创建了一个更全面,更清晰的版本,有些人可能会发现这对于记住哪个名称对应哪个值很有用 . 我使用了Chrome Dev Tool的颜色代码,并且对称地组织标签以更快地获取类比:
注1: clientLeft 还包括垂直滚动条的宽度,如果文本的方向设置为从右到左(因为在这种情况下条形图显示在左侧)
clientLeft
注2:最外面的一行代表最接近的 positioned 父级(一个元素,其 position 属性设置为不同于 static 或 initial 的值) . 因此,如果直接容器不是 positioned 元素,则该行不表示层次结构中的第一个容器,而是表示层次结构中较高的另一个元素 . 如果未找到 positioned parent,则浏览器将使用 html 或 body 元素作为参考
position
static
initial
html
body
希望有人发现它有用,只需我2美分;)
如果你想使用scrollWidth来获取 "REAL" CONTENT WIDTH/HEIGHT (因为内容可能比css定义的宽度/高度框更大) scrollWidth/Height is very UNRELIABLE ,如果内容很大,某些浏览器似乎是"MOVE" paddingRIGHT和paddingBOTTOM . 然后他们将填充物放在"too broad/high content"的右/底部(见下图) .
==> 因此,要在某些浏览器中获取REAL CONTENT WIDTH,您必须从滚动宽度中减去BOTH填充,在某些浏览器中,您只需要减去LEFT Padding .
我找到了一个解决方案,并希望将其添加为注释,但不允许 . 所以我拍了照片,并且在"moved paddings"和"unreliable scrollWidth"方面让它更加清晰 . In the BLUE AREA you find my solution on how to get the "REAL" CONTENT WIDTH!
希望这有助于使事情更清晰!
有一篇关于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,每个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)
div3
bcr.width:265(chrome53,ff49,safari9,edge13,ie11)
bcr.height:165(chrome53,ff49,safari9,edge13,ie11)
clientWidth:503(ie11)
因此,除了edge13和ie11中的boundingClientRect的高度值(299.9999694824219而不是预期的300)之外,结果证实了这背后的理论有效 .
从那里,这是我对这些概念的定义:
offsetWidth / offsetHeight:布局边框的尺寸
boundingClientRect:渲染边框的尺寸
clientWidth / clientHeight:布局填充框可见部分的尺寸(不包括滚动条)
scrollWidth / scrollHeight:布局填充框的尺寸(如果它不受滚动条约束)
注意:默认垂直滚动条的宽度在edge13中为12px,在chrome53中为15px,ff49和safari9,在ie11中为17px(通过截屏中的photoshop测量完成,并通过测试结果证明) .
但是,在某些情况下,您的应用可能没有使用默认的垂直滚动条的宽度 .
因此,给定这些概念的定义,垂直滚动条的宽度应等于(伪代码):
layout dimension:offsetWidth - clientWidth - (borderLeftWidth borderRightWidth)
rendering dimension:boundingClientRect.width - clientWidth - (borderLeftWidth borderRightWidth)
注意,如果您不了解布局与渲染,请阅读mdn文章 .
此外,如果您有其他浏览器(或者如果您想亲自查看测试结果),可以在此处查看我的测试页面:http://codepen.io/lingtalfi/pen/BLdBdL
4 回答
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
考虑了滚动条宽度,我们可以使用它来通过公式计算滚动条宽度不幸的是,我们可能会得到四舍五入的错误,因为
offsetWidth
和clientWidth
总是整数,而实际大小可能是小数,缩放级别不是1 .请注意这一点
not 在Chrome中可靠地运行,因为Chrome返回
width
,滚动条已经减去 . (另外,Chrome会将paddingBottom渲染到滚动内容的底部,而其他浏览器则不会)我创建了一个更全面,更清晰的版本,有些人可能会发现这对于记住哪个名称对应哪个值很有用 . 我使用了Chrome Dev Tool的颜色代码,并且对称地组织标签以更快地获取类比:
注1:
clientLeft
还包括垂直滚动条的宽度,如果文本的方向设置为从右到左(因为在这种情况下条形图显示在左侧)注2:最外面的一行代表最接近的 positioned 父级(一个元素,其
position
属性设置为不同于static
或initial
的值) . 因此,如果直接容器不是 positioned 元素,则该行不表示层次结构中的第一个容器,而是表示层次结构中较高的另一个元素 . 如果未找到 positioned parent,则浏览器将使用html
或body
元素作为参考希望有人发现它有用,只需我2美分;)
如果你想使用scrollWidth来获取 "REAL" CONTENT WIDTH/HEIGHT (因为内容可能比css定义的宽度/高度框更大) scrollWidth/Height is very UNRELIABLE ,如果内容很大,某些浏览器似乎是"MOVE" paddingRIGHT和paddingBOTTOM . 然后他们将填充物放在"too broad/high content"的右/底部(见下图) .
==> 因此,要在某些浏览器中获取REAL CONTENT WIDTH,您必须从滚动宽度中减去BOTH填充,在某些浏览器中,您只需要减去LEFT Padding .
我找到了一个解决方案,并希望将其添加为注释,但不允许 . 所以我拍了照片,并且在"moved paddings"和"unreliable scrollWidth"方面让它更加清晰 . In the BLUE AREA you find my solution on how to get the "REAL" CONTENT WIDTH!
希望这有助于使事情更清晰!
有一篇关于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,每个div包含10个lorem ipsum段落 . 一些CSS适用于他们:
以下是结果:
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中为15px,ff49和safari9,在ie11中为17px(通过截屏中的photoshop测量完成,并通过测试结果证明) .
但是,在某些情况下,您的应用可能没有使用默认的垂直滚动条的宽度 .
因此,给定这些概念的定义,垂直滚动条的宽度应等于(伪代码):
layout dimension:offsetWidth - clientWidth - (borderLeftWidth borderRightWidth)
rendering dimension:boundingClientRect.width - clientWidth - (borderLeftWidth borderRightWidth)
注意,如果您不了解布局与渲染,请阅读mdn文章 .
此外,如果您有其他浏览器(或者如果您想亲自查看测试结果),可以在此处查看我的测试页面:http://codepen.io/lingtalfi/pen/BLdBdL