JS 中 offsetHeight/scrollHeight/clientHeight 的区别

308 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

JS 基于 DOM 对象可以拿到元素的宽高的属性有 offset 系、scroll 系、client 系(以其名称作为前缀得名),IDE 提示如下(以 VS Code 为准)

接下来就以如下顺序介绍一下这三种获取宽高的方法,以及它们的不同

  1. client*
  2. offset*
  3. scroll*

client

  1. client*
    1. clientWidth/clientHeight 返回的是元素的内部宽度,它的值只包含 content + padding,如果有滚动条,不包含滚动条
    2. clientTop 返回的是上边框的宽度
    3. clientLeft 返回的左边框的宽度
<body>
  <div class="demo" style="height: 100px; width: 100px; padding: 10px;"></div>
</body>
<script>
  const div = document.querySelector(".demo");
  console.log(div.clientWidth, div.clientHeight, div.clientTop, div.clientLeft);
  // 120 120 10 10
</script>

可能有人想问了,clientBottom 是不是就是 border 底部的值呢?实际上结果是 undefiend 因为并没有这个值,clientRight 同理

注意一个小细节

clientHeightclientWidth 不包括滚动条,如果有滚动条,那么 clientHeight = content + padding - scroll (元素内容本身的高度加上内边距再减去水平滚动条的高度)

<body>
  <div
    class="demo"
    style="
      height: 100px;
      width: 100px;
      padding: 10px;
      border: 10px solid black;
      overflow: auto;
    "
  >
    <div style="height: 200px"></div>
  </div>
</body>
<script>
  const div = document.querySelector(".demo");
  console.log(div.clientWidth, div.clientHeight); // 103 120
  // 此时滚动条宽度为 17px
</script>

offset

  1. offset*
    1. offsetWidth/offsetHeight 返回的是元素的布局宽度,它的值包含 content + padding + border 包含了滚动条
    2. offsetTop 返回的是当前元素相对于其 offsetParent 元素的顶部的距离
    3. offsetLeft 返回的是当前元素相对于其 offsetParent 元素的左部的距离

不过有点奇怪的是,VS CodeWebStorm 都没有对 offset* 做任何提示(希望评论区能够给出答案)

依旧是上面的例子

<body>
  <div style="height: 100px"></div>
  <div
    class="demo"
    style="
      height: 100px;
      width: 100px;
      padding: 10px;
      border: 10px solid black;
      overflow: auto;
    "
  >
    <div style="height: 200px"></div>
  </div>
</body>
<script>
  const div = document.querySelector(".demo");
  console.log(div.offsetHeight, div.offsetWidth, div.offsetTop, div.offsetLeft);
  // 140 140 108 8
</script>

此时 divoffsetParent 就是 body

scroll

  1. scroll*
    1. scrollWidth/scrollHeight 返回值包含 content + padding + 溢出内容的尺寸
    2. scrollTop 属性返回的是一个元素的内容垂直滚动的像素数
    3. scrollLeft 读写元素左侧已滚动的距离,即位于元素左边界与元素中当前可见内容的最左端之间的距离。

scrollWidth/Height 不多讲了,和 offset 差不多以及 client 系差不多,接下来用两个动图介绍一下 scrollTopscrollLeft

scrollLeft 的数值就是已经滑动、消失的部分和当前可见区域最左边的距离

代码如下

<body>
  <div
    class="demo"
    style="
      transform: translate(0, 0);
      height: 200px;
      width: 200px;
      padding: 10px;
      border: 10px solid black;
      overflow: auto;
    "
  >
    <div style="height: 50px; width: 800px; background: black"></div>
    <div class="count" style="position: sticky; left: 0">scrollLeft: 0</div>
  </div>
</body>
<script>
  const div = document.querySelector(".demo");
  const count = document.querySelector(".count");
  div.addEventListener("scroll", () => {
    count.innerHTML = "scrollLeft: " + parseInt(div.scrollLeft);
  });
</script>

参考资料

  1. JS scrollLeft和scrollTop属性:读写元素左侧和顶部已滚动的距离
  2. 浅谈JS各种宽高(clientHeight、scrollHeight、offsetHeight等)- CSDN - 骆小胖