分别了解offsetWidth,clientWidth,scrollWidth和-Height


385

在StackOverflow上有几个关于offsetWidth / clientWidth / scrollWidth(和-Height分别)的问题,但是没有一个问题可以全面解释这些值是什么。

另外,网络上有多个来源提供令人困惑或不正确的信息。

您能否给出完整的解释,包括一些视觉提示?另外,这些值如何用于计算滚动条宽度?

Answers:


868

CSS盒子模型相当复杂,尤其是在滚动内容时。尽管浏览器使用CSS中的值来绘制框,但是如果您只有CSS,则使用JS确定所有尺寸并不是直截了当的。

这就是为什么每个元素都为您提供方便6个DOM属性:offsetWidthoffsetHeightclientWidthclientHeightscrollWidthscrollHeight。这些是代表当前视觉布局的只读属性,并且它们都是整数(因此可能会舍入错误)。

让我们详细了解一下它们:

  • offsetWidthoffsetHeight:包括所有边框的可视框的大小。可以通过添加width/ height以及填充和边框(如果元素具有display: block
  • clientWidthclientHeight:框内容的可视部分,不包括边框或滚动条,但包括padding。不能直接从CSS计算,取决于系统的滚动条大小。
  • scrollWidthscrollHeight:框的所有内容的大小,包括当前隐藏在滚动区域之外的部分。不能直接从CSS计算,取决于内容。

CSS2盒子模型

试试看:jsFiddle


由于offsetWidth考虑了滚动条的宽度,因此我们可以通过公式使用它来计算滚动条的宽度

scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth

不幸的是,由于offsetWidthclientWidth始终是整数,因此我们可能会舍入错误,而实际大小可能是除1以外的缩放级别的分数。

请注意

scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth

在Chrome浏览器中无法正常运行,因为Chrome浏览器返回width时已扣除滚动条。(此外,Chrome会将paddingBottom渲染到滚动内容的底部,而其他浏览器则不这样做)


27
对于那些寻求比整数更精细的粒度的用户,请使用element.getBoundingClientRect()(请参阅developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth上的说明)
Anson Kao 2014年

1
请注意,根据您的布局,scrollWidth和scrollHeight对于获取伪元素:: before和:: after的大小非常有用。
David

此外,它会解释如何做那些涉及到有用naturalWidthnaturalHeight
YakovL

为什么scrollHeight包括padding-bottomscrollWidth不包括padding-right
JunGor

clientWidth对于document.documentElement.clientWidth是不同的,因为它似乎包括paddingbordersmargin
Drenai

49

我创建了一个更全面,更简洁的版本,有些人可能会觉得对记住哪个名称对应哪个值很有用。我使用Chrome Dev Tool的颜色代码和标签是对称组织的,以便更快地提取类比:

在此处输入图片说明

  • 注意1:clientLeft如果文本的方向设置为从右到左,则还包括垂直滚动条的宽度(因为在这种情况下,该条显示在左侧)

  • 注2:最外层线表示最接近定位父(一个元件,其position属性被设置为一个值不同于 staticinitial)。因此,如果直接容器不是定位的 元素,则该行不代表层次结构中的第一个容器,而是代表层次结构中较高的另一个元素。如果找不到 定位的父级,浏览器将以htmlbody 元素作为参考


希望有人发现它有用,只有我的2美分;)


30

如果您想使用scrollWidth来获取“ REAL” 内容的宽度/高度(因为内容可能比css定义的width / height-Box 更大),scrollWidth / Height是非常不可靠的,因为某些浏览器似乎在“移动” paddingRIGHT &paddingBOTTOM(如果内容太大)。然后,他们将填充物放在“太宽/太高的内容”的右/底部(请参见下图)。

==>因此,要在某些浏览器中获得真实内容宽度,您必须从scrollwidth中减去两个填充,而在某些浏览器中,您仅需减去LEFT Padding。

我为此找到了解决方案,并希望将其添加为注释,但不允许这样做。所以我拍了张照片,使它的“移动的填充”和“不可靠的scrollWidth”更加清晰了。在蓝色区域中,您可以找到有关如何获得“真实”内容宽度的解决方案!

希望这有助于使事情变得更加清晰!

在此处输入图片说明


13

关于MDN的一篇很好的文章解释了这些概念背后的理论:https//developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Det​​ermining_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(即11)
    • 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中通过屏幕截图进行测量,并通过测试结果进行了验证)。

但是,在某些情况下,您的应用可能未使用默认的垂直滚动条的宽度。

因此,给定这些概念的定义,垂直滚动条的宽度应等于(用伪代码):

  • 布局尺寸:offsetWidth-clientWidth-(borderLeftWidth + borderRightWidth)

  • 呈现尺寸:boundingClientRect.width-clientWidth-(borderLeftWidth + borderRightWidth)

请注意,如果您不了解布局与渲染,请阅读mdn文章。

另外,如果您使用其他浏览器(或者想要自己查看测试结果),则可以在此处查看我的测试页:http : //codepen.io/lingtalfi/pen/BLdBdL

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.