【问题标题】:clientWidth and clientHeight report zero while getBoundingClientRect is correct当 getBoundingClientRect 正确时,clientWidth 和 clientHeight 报告为零
【发布时间】:2015-12-03 00:11:22
【问题描述】:

在 MDN 的 description of Element.clientWidth 中它说。

注意:我已经根据@potatopeelings 的答案更新了 MDN。

Element.clientWidth 属性是元素的内部宽度(以像素为单位)。它包括填充,但不包括垂直滚动条(如果存在,如果呈现)、边框或边距。

此属性会将值四舍五入为整数。如果需要小数值,请使用 element.getBoundingClientRect()。

据我了解,除了四舍五入之外,clientWidth 应该与getBoundingClientRect().width 相同。

但是我发现对于许多元素(displayinline?)clientWidth(和高度)为零,而 getBoundingClientRect 返回的值似乎是正确的。

在 stackoverflow 上搜索会得到一些答案,说这发生在文档处于 ready 状态之前,但我一直都看到这种情况,而不仅仅是在页面加载时。

我检查过的所有浏览器的这种行为都是一致的,它在哪里指定应该是这种行为?

示例:

function str(name, width, height) {
  return name + ': (' + width + ', ' + height + ')';
}

function test() {
  var s = document.getElementById('s');
  var rect = s.getBoundingClientRect();
  document.getElementById('out').innerHTML =
    str('client', s.clientWidth, s.clientHeight) + '<br/>' +
    str('bounding', rect.width, rect.height);
}
 <span id="s">A span</span><br/> <button onclick="test()">Test</button>
<hr />
<div id="out"></div>

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    来自规范 (http://www.w3.org/TR/cssom-view/#dom-element-clientwidth)

    clientWidth 属性必须运行以下步骤:

    1.如果元素没有关联的CSS布局框或者如果CSS布局框是内联的,则返回
    ...

    【讨论】:

    • 就是这样!你知道这是为什么吗?
    • 我相信它在规范中已经有很长一段时间了 - 我能找到的最早参考是 lists.w3.org/Archives/Public/www-style/2008Mar/0060.html(从 2008 年开始),但我很确定会有更旧的参考,甚至如果您使用特定于浏览器的旧参考。
    • 今天发生在我身上。尽管元素 have display: block clientHeight 会返回 0。那是因为我在另一个地方使用了 .innerHTML (developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML),甚至是另一个文件。在这样做并添加 HTML 的同时,我测量的所有其他元素的高度都会返回 0。一旦我在DOMContentLoaded 事件中添加了 HTML,一切正常,并返回元素的实际高度。所以要小心,当你将 HTML 添加到另一个地方的 DOM 时,clientWidth 和 clientHeight 将/可能是 0。
    【解决方案2】:

    除了@potatopeelings 的回答:

    内联元素没有固有的或指定的尺寸。例如。您不能为 span 定义宽度(除非您更改它的 display 属性)。

    clientWidthgetBoundingClientRect 也有不同的用途,可能返回不同的值。后者还考虑转换并返回元素实际呈现时的尺寸。

    .class {
      transform: scale(0.5);
    }
    

    如果 clientWidth 在这种情况下返回 1000,那么 getBoundingClientRect 的宽度将为 500。

    您可以将clientWidth 视为“我在元素内有多少可用空间”,将getBoundingClientRect 视为“元素在屏幕上占用多少空间”。所以在我们的例子中,元素将有足够的空间来并排包含两个 500 像素的元素,并且它会在屏幕上占据 500 像素。

    【讨论】:

    • css 生活在语义混乱的海洋中,因此感谢您阐明这两个属性如何被感知。
    【解决方案3】:

    getBoundingClientRect() 的返回值是一个 DOMRect 对象,它是 getClientRects() 为元素返回的矩形的并集;即使元素是内联的,此方法也会查看边界框尺寸(它没有 clientWidth 具有的内联元素的限制 - 规范 @potatopeelings 链接)。

    function str(name, width, height) {
      return name + ': (' + width + ', ' + height + ')';
    }
    
    function test() {
      var s = document.getElementById('s');
      var rect = s.getBoundingClientRect();
      document.getElementById('out').innerHTML =
        str('client', s.clientWidth, s.clientHeight) + '<br/>' +
        str('bounding', rect.width, rect.height);
    }
    #s{
      display: inline-block
    }
    <span id="s">A span</span><br/> <button onclick="test()">Test</button>
    <hr />
    <div id="out"></div>

    将显示属性更改为inline-blockblock 时检查差异。

    【讨论】:

      猜你喜欢
      • 2012-07-30
      • 2019-09-17
      • 1970-01-01
      • 2013-04-20
      • 2021-02-21
      • 2020-03-11
      • 2020-01-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多