前端
HTML&CSS
元素的大小及位置

clientWidth 和 clientHeight

clientWidth (opens in a new tab)clientHeight (opens in a new tab) 属性返回元素的内容区的宽度和高度,不包括边框、滚动条和内边距。

clientWidth and clientHeight
  • 它是个只读属性
  • 对于 html 和 body 的 clientHeight,返回的是 viewport 的高度,不算滚动条
  • 对于 inline box 的元素,获取的值为 0 (zero for elements with no CSS or inline layout boxes)

offsetWidth 和 offsetHeight

offsetWidth (opens in a new tab)offsetHeight (opens in a new tab) 属性返回元素的内容区的宽度和高度,包括内边距、滚动条和边框

offsetWidth and offsetHeight
  • 它是一个只读属性
  • 是 CSS 高度的衡量标准,包括元素的边框、内边距和元素的水平滚动条(如果存在且渲染的话),不包含:before 或:after 等伪类元素的高度
  • 如果元素被隐藏(元素或者元素的祖先之一的元素的 style.display 被设置为 none),则返回 0
  • offsetHeight 会被四舍五入为整数值,如果需要一个浮点数值,请用 element.getBoundingClientRect()

对比 clientHeight 和 offsetHeight

offsetHeight = Visible content height + padding + border + scrollbar

clientHeight = Visible content height + padding

innerWidth 和 innerHeight

innerWidth (opens in a new tab)innerHeight (opens in a new tab) 属性返回窗口的视口的宽度和高度。这些属性是只读的,但是可以通过设置 window.resizeTo() (opens in a new tab)window.resizeBy() (opens in a new tab) 来改变窗口的大小。

获取浏览器视口高度的兼容写法

const height =
  window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

outerWidth 和 outerHeight

outerWidth (opens in a new tab)outerHeight (opens in a new tab) 属性返回浏览器的宽度和高度,以像素计,包括工具栏/滚动条的宽度。

outerWidth

scroll 相关 API


1. scrollWidth (opens in a new tab)scrollHeight (opens in a new tab) 属性返回元素的内容区的宽度和高度,包括内边距由于溢出导致的视图中不可见内容,但不包括滚动条、边框和外边距。

scrollHeight
  • 它是一个只读属性
  • 一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容
  • 没有垂直滚动条的情况下,scrollHeight 值与元素视图填充所有内容所需要的最小值 clientHeight 相同
  • scrollHeight 也包括::before,::after 这样的伪元素

2. scrollLeft (opens in a new tab)scrollTop (opens in a new tab) 属性返回元素的内容区的左上角相对于元素左上角的偏移量,可以修改。

  • Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。
  • Element.scrollLeft 属性可以读取或设置元素滚动条到元素左边的距离。

需要额外注意的是: 注意如果这个元素的内容排列方向(direction) 是 rtl (right-to-left) ,那么滚动条会位于最右侧(内容开始处),并且 scrollLeft 值为 0。此时,当你从右到左拖动滚动条时,scrollLeft 会从 0 变为负数。

const button = document.getElementById("slide");
 
button.onclick = () => {
  document.getElementById("container").scrollLeft += 20;
};

3. Element.scroll() (opens in a new tab) 方法滚动元素的内容区域,使得指定的元素的左上角出现在视图中的指定坐标处。

// 方法一
element.scroll(x-coord, y-coord)
element.scroll(options)
 
// 方法二
// 同时也支持 `element.scroll(options)` 方式调用,支持传入额外的配置:
{
    left: number,
    top: number,
    behavior: 'smooth' | 'auto' // 平滑滚动还是默认直接滚动
}
  • x-coord 是指在元素左上方区域横轴方向上想要显示的像素。
  • y-coord 是指在元素左上方区域纵轴方向上想要显示的像素。

判断当前元素是否存在滚动条,出现滚动条便意味着元素空间将大于其内容显示区域,根据这个现象便可以得到判断是否出现滚动条的规则。

export const hasScrolled = (element, direction) => {
  if (!element || element.nodeType !== 1) return;
  if (direction === "vertical") {
    return element.scrollHeight > element.clientHeight;
  } else if (direction === "horizontal") {
    return element.scrollWidth > element.clientWidth;
  }
};

判断用户是否滚动到底部,本质上就是当元素出现滚动条时,判断当前元素出现的高度 + 滚动条高度 = 元素本身的高度(包含隐藏部分)

element.scrollHeight - element.scrollTop === element.clientHeight;

getBoundingClientRect()

getBoundingClientRect() (opens in a new tab) 方法返回元素的大小及其相对于视口的位置。

getBoundingClientRect

element.getBoundingClientRect()返回的 height 和 width 是针对元素可见区域的宽和高(具体尺寸根据 box-sizing 决定),并不包含滚动条被隐藏的内容。

如果是标准盒子模型,元素的尺寸等于 width/height + padding + border-width 的总和。如果 box-sizing: border-box,元素的的尺寸等于 width/height。

计算元素是否出现在视口内 利用的还是元素距离视口的位置小于视口的大小。

注意即便变成了负值,那么也表示元素曾经出现过在屏幕中只是现在不显示了而已。(就比如滑动过)

vue-lazy 图片懒加载库源码就是这么判断的。

isInView (): boolean {
    const rect = this.el.getBoundingClientRect()
    return rect.top < window.innerHeight && rect.left < window.innerWidth
  }

如果 rect.top < window.innerHeight 表示当前元素已经已经出现在(过)页面中,left 同理。

getClientRects()

getClientRects() (opens in a new tab) 方法返回一个包含元素的所有盒子的列表,这些盒子是元素的边框,以及元素的内边距和边框。