Html 分别理解offsetWidth、clientWidth、scrollWidth和-Height

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21064101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 00:27:27  来源:igfitidea点击:

Understanding offsetWidth, clientWidth, scrollWidth and -Height, respectively

htmlcssdom

提问by user123444555621

There are several questions on StackOverflow regarding offsetWidth/clientWidth/scrollWidth (and -Height, respectively), but none give comprehensive explanation of what those values are.

StackOverflow 上有几个关于 offsetWidth/clientWidth/scrollWidth(分别是 -Height)的问题,但没有人给出这些值的全面解释。

Also, there are several sources on the web giving confusing or incorrect information.

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

Can you give a complete explanation including some visual hints? Also, how can those values be used to calculate scroll bar widths?

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

回答by user123444555621

The CSS box model is rather complicated, particularly when it comes to scrolling content. While the browser uses the values from your CSS to draw boxes, determining all the dimensions using JS is not straight-forward if you only have the CSS.

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

That's why each element has six DOM properties for your convenience: offsetWidth, offsetHeight, clientWidth, clientHeight, scrollWidthand scrollHeight. These are read-only attributes representing the current visual layout, and all of them are integers(thus possibly subject to rounding errors).

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

Let's go through them in detail:

让我们详细介绍一下它们:

  • offsetWidth, offsetHeight: The size of the visual box incuding all borders. Can be calculated by adding width/heightand 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.
  • offsetWidth, offsetHeight: 包含所有边框的可视框的大小。可以通过添加width/height和 paddings 和边框来计算,如果元素有display: block
  • clientWidth, clientHeight: 框内容的可视部分,不包括边框或滚动条,但包括 padding 。不能直接从 CSS 计算,取决于系统的滚动条大小。
  • scrollWidth, scrollHeight: 框的所有内容的大小,包括当前隐藏在滚动区域之外的部分。不能直接从 CSS 计算,取决于内容。

CSS2 Box Model

CSS2 盒子模型

Try it out: jsFiddle

试试看:jsFiddle



Since offsetWidthtakes the scroll bar width into account, we can use it to calculate the scroll bar width via the formula

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

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

Unfortunately, we may get rounding errors, since offsetWidthand clientWidthare always integers, while the actual sizes may be fractional with zoom levels other than 1.

不幸的是,我们可能会得到舍入错误,因为offsetWidthclientWidth总是整数,而实际大小可能是小数,缩放级别不是 1。

Note that this

请注意,这

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

does notwork reliably in Chrome, since Chrome returns widthwith scrollbar already substracted. (Also, Chrome renders paddingBottom to the bottom of the scroll content, while other browsers don't)

在 Chrome中不能可靠地工作,因为 Chrome 返回width时已经减去了滚动条。(此外,Chrome 将 paddingBottom 渲染到滚动内容的底部,而其他浏览器则不会)

回答by Lual

I created a more comprehensive and cleaner version that some people might find useful for remembering which name corresponds to which value. I used Chrome Dev Tool's color code and labels are organized symmetrically to pick up analogies faster:

我创建了一个更全面和更清晰的版本,有些人可能会发现它有助于记住哪个名称对应哪个值。我使用 Chrome Dev Tool 的颜色代码和标签对称组织以更快地进行类比:

enter image description here

在此处输入图片说明

  • Note 1: clientLeftalso 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 positionedparent (an element whose positionproperty is set to a value different than staticor initial). Thus, if the direct container isn't a positionedelement, then the line doesn't represent the first container in the hierarchy but another element higher in the hierarchy. If no positionedparent is found, the browser will take the htmlor bodyelement as reference

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

  • 注 2:最外面的一行代表最近定位的父元素(其position属性设置为不同于static或的值 的元素initial)。因此,如果直接容器不是定位元素,则该行不代表层次结构中的第一个容器,而是层次结构中更高的另一个元素。如果没有 找到定位的父 元素,浏览器将把htmlorbody元素作为引用



Hope somebody finds it useful, just my 2 cents ;)

希望有人觉得它有用,只有我的 2 美分 ;)

回答by Manny_user3297459

If you want to use scrollWidth to get the "REAL"CONTENT WIDTH/HEIGHT(as content can be BIGGER than the css-defined width/height-Box) the scrollWidth/Height is very UNRELIABLEas some browser seem to "MOVE" the paddingRIGHT & paddingBOTTOM if the content is to big. They then place the paddings at the RIGHT/BOTTOM of the "too broad/high content" (see picture below).

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

==>Therefore to get the REAL CONTENT WIDTH in some browsers you have to substract BOTH paddings from the scrollwidth and in some browsers you only have to substract the LEFT Padding.

==>因此,要在某些浏览器中获得真正的内容宽度,您必须从滚动宽度中减去两个填充,而在某些浏览器中,您只需要减去左填充。

I found a solution for this and wanted to add this as a comment, but was not allowed. So I took the picture and made it a bit clearer in the regard of the "moved paddings" and the "unreliable scrollWidth". In the BLUE AREA you find my solution on how to get the "REAL" CONTENT WIDTH!

我为此找到了解决方案,并想将此添加为评论,但不允许。所以我拍了这张照片,并在“移动的填充”和“不可靠的滚动宽度”方面让它更清晰一些。在蓝色区域中,您可以找到有关如何获得“真实”内容宽度的解决方案!

Hope this helps to make things even clearer!

希望这有助于使事情更清楚!

enter image description here

在此处输入图片说明

回答by ling

There is a good article on MDN that explains the theory behind those concepts: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements

MDN 上有一篇很好的文章解释了这些概念背后的理论:https: //developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Det​​ermining_the_dimensions_of_elements

It also explains the important conceptual differences between boundingClientRect's width/height vs offsetWidth/offsetHeight.

它还解释了 boundingClientRect 的宽度/高度与 offsetWidth/offsetHeight 之间的重要概念差异。

Then, to prove the theory right or wrong, you need some tests. That's what I did here: https://github.com/lingtalfi/dimensions-cheatsheet

然后,要证明理论是对还是错,您需要进行一些测试。这就是我在这里所做的:https: //github.com/lingtalfi/dimensions-cheatsheet

It's testing for chrome53, ff49, safari9, edge13 and ie11.

它正在测试 chrome53、ff49、safari9、edge13 和 ie11。

The results of the tests prove that the theory is generally right. For the tests, I created 3 divs containing 10 lorem ipsum paragraphs each. Some css was applied to them:

测试结果证明该理论总体上是正确的。对于测试,我创建了 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);
}

And here are the results:

结果如下:

  • 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)
  • div1

    • offsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
    • 偏移高度:330(chrome53、ff49、safari9、edge13、ie11)
    • bcr.width: 530 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 330 (chrome53, ff49, safari9, edge13, ie11)

    • 客户端宽度:505(chrome53、ff49、safari9)

    • 客户端宽度:508(edge13)
    • 客户端宽度:503(ie11)
    • 客户端高度:320(chrome53、ff49、safari9、edge13、ie11)

    • 滚动宽度:505(chrome53、safari9、ff49)

    • 滚动宽度:508(edge13)
    • 滚动宽度:503(ie11)
    • 滚动高度:916(chrome53,safari9)
    • 滚动高度:954 (ff49)
    • 滚动高度: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)
    • 客户端宽度:475(chrome53、ff49、safari9)
    • 客户端宽度:478(edge13)
    • 客户端宽度:473(ie11)
    • 客户端高度:290(chrome53、ff49、safari9、edge13、ie11)

    • 滚动宽度:475(chrome53、safari9、ff49)

    • 滚动宽度:478(edge13)
    • 滚动宽度:473(ie11)
    • 滚动高度:916(chrome53,safari9)
    • 滚动高度:954 (ff49)
    • 滚动高度:922(edge13,ie11)
  • div3

    • offsetWidth: 530 (chrome53, ff49, safari9, edge13, ie11)
    • 偏移高度:330(chrome53、ff49、safari9、edge13、ie11)
    • bcr.width: 265 (chrome53, ff49, safari9, edge13, ie11)
    • bcr.height: 165 (chrome53, ff49, safari9, edge13, ie11)
    • 客户端宽度:505(chrome53、ff49、safari9)
    • 客户端宽度:508(edge13)
    • 客户端宽度:503(ie11)
    • 客户端高度:320(chrome53、ff49、safari9、edge13、ie11)

    • 滚动宽度:505(chrome53、safari9、ff49)

    • 滚动宽度:508(edge13)
    • 滚动宽度:503(ie11)
    • 滚动高度:916(chrome53,safari9)
    • 滚动高度:954 (ff49)
    • 滚动高度:922(edge13,ie11)

So, apart from the boundingClientRect's height value (299.9999694824219 instead of expected 300) in edge13 and ie11, the results confirm that the theory behind this works.

因此,除了 edge13 和 ie11 中 boundingClientRect 的高度值(299.9999694824219 而不是预期的 300)之外,结果证实了这背后的理论是有效的。

From there, here is my definition of those concepts:

从那里开始,这是我对这些概念的定义:

  • offsetWidth/offsetHeight: dimensions of the layout border box
  • boundingClientRect: dimensions of the rendering border box
  • clientWidth/clientHeight: dimensions of the visible part of the layout padding box (excluding scroll bars)
  • scrollWidth/scrollHeight: dimensions of the layout padding box if it wasn't constrained by scroll bars
  • offsetWidth/offsetHeight:布局边框框的尺寸
  • boundingClientRect:渲染边框框的尺寸
  • clientWidth/clientHeight:布局填充框可见部分的尺寸(不包括滚动条)
  • scrollWidth/scrollHeight:布局填充框的尺寸,如果它不受滚动条的约束

Note: the default vertical scroll bar's width is 12px in edge13, 15px in chrome53, ff49 and safari9, and 17px in ie11 (done by measurements in photoshop from screenshots, and proven right by the results of the tests).

注意:默认垂直滚动条的宽度在 edge13 中为 12px,在 chrome53、ff49 和 safari9 中为 15px,在 ie11 中为 17px(通过截图在 photoshop 中的测量完成,并通过测试结果证明是正确的)。

However, in some cases, maybe your app is not using the default vertical scroll bar's width.

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

So, given the definitions of those concepts, the vertical scroll bar's width should be equal to (in pseudo code):

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

  • layout dimension: offsetWidth - clientWidth - (borderLeftWidth + borderRightWidth)

  • rendering dimension: boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)

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

  • 渲染维度:boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)

Note, if you don't understand layout vs rendering please read the mdn article.

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

Also, if you have another browser (or if you want to see the results of the tests for yourself), you can see my test page here: http://codepen.io/lingtalfi/pen/BLdBdL

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