关于html:分别了解offsetWidth,clientWidth,scrollWidth和-Height

Understanding offsetWidth, clientWidth, scrollWidth and -Height, respectively

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

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

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


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

因此,为方便起见,每个元素都有六个DOM属性:offsetWidthoffsetHeightclientWidthclientHeightscrollWidthscrollHeight。这些是代表当前视觉布局的只读属性,并且它们都是整数(因此可能会产生舍入误差)。

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

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

CSS2 Box Model

试试看:jsFiddle

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

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

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

注意这个

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

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


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

enter image description here

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

  • 注2:最外面的线表示最接近的父级
    (其position属性设置为与
    staticinitial)。因此,如果直接容器不在
    元素,则该行不代表中的第一个容器
    层次结构中的另一个元素。如果不
    找到定位的父对象,浏览器将使用htmlbody
    元素作为参考

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


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

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

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

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

enter image description here


关于MDN的一篇很好的文章解释了这些概念背后的理论:
https://developer.mozilla.org/zh-CN/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应用于它们:

好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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

    好。

    好。