JavaScript | 元素常用定位、大小相关的属性

前言

之前一篇文章写了以下滚动事件相关的知识点(链接),但是只是知道滚动事件肯定是不行的。

比如,现在有一个需求,在页面上滚动到某个元素的时候就显示回到页面顶部的按钮。

一看到这个需求,首先想到的就是使用滚动事件,但是,问题就来了,怎么知道现在滚动到了这个元素呢?

这里就会涉及到WEB API中常用的一些元素定位以及大小相关的属性,打算通过这篇文章整理一下这块的知识点。

scrollHeight/scrollWidth/scrollTop/scrollLeft

首先要介绍的属性是scroll系列的属性,它们都是以scroll作为属性名称的开头,下面简单来介绍下这些属性的具体含义,首先看下MDN官网对于这些属性的定义:

  • Element.scrollHeight:这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。
  • Element.scrollWidth:这个只读属性是元素内容宽度的一种度量,包括由于 overflow 溢出而在屏幕上不可见的内容。
  • Element.scrollLeft:属性可以读取或设置元素滚动条到元素左边的距离。
  • Element.scrollTop:属性可以获取或设置一个元素的内容垂直滚动的像素数。

根据上面的定义,画了下下面这张图,可以通过这张图对这几个属性进行理解

截图

所以简单总结一下:

  • 当需要获取元素内容的宽度和高度的时候,使用scrollWidthscrollHeight(只读属性,不返回单位)
  • 如果要获取元素滚动的距离(元素内容向右边或者是向下滚动后,可视窗口看不到的已经滚动的距离),使用scrollLeftscrollTop,与刚才那两个属性不同,这个属性是可以进行设置修改的

在实际开发过程中,使用scrollTop属性比较多,比如:页面滚动200px设置某个元素显示,代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 获取元素
let backToTop = document.querySelector('.backtotop');
// 给页面添加事件监听
window.addEventListener('scroll', ()=>{
  // 检测页面滚动的距离
  let PageScrollTop = document.documentElement.scrollTop;
  // 如果页面滚动到200px的位置,显示元素
  if (num >= 200) {
    backToTop.style.opacity = 1.0;
  } else {
    backToTop.style.opacity = 0;
  }
})

备注:

Document.documentElement 是一个会返回文档对象(document)的根元素的只读属性(如HTML文档的 元素)。

offsetHeight/offsetWidth/offsetTop/offsetLeft

接下来要介绍的是offset系列的属性,它们都是以offset作为属性名称的开头,下面简单来介绍下这些属性的具体含义,首先看下MDN官网对于这些属性的定义:

  • HTMLElement.offsetHeight 是一个只读属性,它返回该元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数。
  • HTMLElement.offsetWidth 是一个只读属性,返回一个元素的布局宽度。一个典型的(译者注:各浏览器的 offsetWidth 可能有所不同)offsetWidth 是测量包含元素的边框 (border)、水平线上的内边距 (padding)、竖直方向滚动条 (scrollbar)(如果存在的话)、以及 CSS 设置的宽度 (width) 的值。
  • HTMLElement.offsetTop 为只读属性,它返回当前元素相对于其 offsetParent 元素的顶部内边距的距离。
  • HTMLElement.offsetLeft 是一个只读属性,返回当前元素左上角相对于 HTMLElement.offsetParent 节点的左边界偏移的像素值。

根据上面的定义,画了下下面这张图,可以通过这张图对这几个属性进行理解

截图

简单做个总结:

  • 获取元素在页面中的位置的时候,我们可以使用offsetLeftoffsetTop这两个属性
    • 可以获取元素相对于自身定位父级元素offsetParent)的left以及top的距离
    • 有关offsetParent这个属性请查看这里(HTMLElement.offsetParent

      HTMLElement.offsetParent 是一个只读属性,返回一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的 table, td, th, body 元素。当元素的 style.display 设置为 "none" 时,offsetParent 返回 null。offsetParent 很有用,因为 offsetTop 和 offsetLeft 都是相对于其内边距边界的。

  • 获取元素的宽高,使用offsetLeftoffsetTop属性
    • 返回值为不包括元素的margin
  • ❕注意:这里的4个属性都是只读属性

那么前言中有提到有个需求就是获取元素在页面中的位置,所以就可以通过offsetTop这个属性就可以实现这个需求,对应的js代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 获取元素
let backToTop = document.querySelector('.backtotop');
// 获取元素在页面中的位置
let bttOt = backToTop.offsetTop;
// 给页面添加事件监听
window.addEventListener('scroll', ()=>{
  // 检测页面滚动的距离
  let PageScrollTop = document.documentElement.scrollTop;
  // 如果页面滚动距离大于该元素的offsetTop则显示该元素
  if (num >= bttOt) {
    backToTop.style.opacity = 1.0;
  } else {
    backToTop.style.opacity = 0;
  }
})

clientHeight/clientWidth/clientLeft/clientTop

最后要介绍的是client系列的属性,它们都是以client作为属性名称的开头,下面简单来介绍下这些属性的具体含义,首先看下MDN官网对于这些属性的定义:

  • Element.clientHeight:只读属性 Element.clientHeight 对于没有定义 CSS 或者内联布局盒子的元素为 0;否则,它是元素内部的高度(以像素为单位),包含内边距,但不包括边框、外边距和水平滚动条(如果存在)。
  • Element.clientWidth:只读属性 Element.clientWidth 对于内联元素以及没有 CSS 样式的元素为 0;否则,它是元素内部的宽度(以像素为单位)。该属性包括内边距(padding),但不包括边框(border)、外边距(margin)和垂直滚动条(如果存在)。
  • Element.clientLeft:表示一个元素的左边框的宽度,以像素表示。如果元素的文本方向是从右向左(RTL, right-to-left),并且由于内容溢出导致左边出现了一个垂直滚动条,则该属性包括滚动条的宽度。clientLeft 不包括左外边距和左内边距。clientLeft 是只读的。
  • Element.clientTop:一个元素顶部边框的宽度(以像素表示)。不包括顶部外边距或内边距。clientTop 是只读的。

MDN上有对前两个属性给出对应的图解,如下:

截图

所以做个总结:

  • clientWidthclientHeight获取的是元素的可见部分的宽高
    • 这里的可见部分不包括元素的边框,以及滚动条
  • 获取左边框和上边框宽度,使用clientLeftclientTop
    • 开发中使用比较少,了解一下
  • 关于clientWidthclientHeight的使用场景
    • 比如检测页面滚动到底部,可以参考这篇文章——链接
    • 还有一种是在一些比较老的网站上可能会见到的一种写法,就是通过这个属性来做页面的自适应
      • 窗口尺寸改变的时候触发事件,对应的事件名称(resize):
      1
      2
      3
      
      window.addEventListener('resize', function() {
      // 执行的代码
      })
      
      • 检测屏幕宽度,改变背景
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      // 当窗口发生变化的时候触发的事件
      window.addEventListener('resize', function(){
      let w = document.documentElement.clientWidth;
      if (w >= 1920) {
          document.body.style.background = 'red';
      } else if(w > 540){
          document.body.style.background = 'blue';
      } else {
          document.body.style.background = 'black';
      }
      });
      

参考文献