无论在 iOS 还是前端开发中,关于如何定位一个元素是必须要掌握的知识,而在前端中,元素定位比较难理解,我们今天一起学习下。

在 DOM 设计中,主要通过这些 API 来确定某个元素的具体位置。

offsetTop, offsetLeft, offsetWidth, offsetHeight,

scrollTop, scrollLeft, scrollWidth, scrollHeight,

clientTop, clientLeft, clientWidth, clientHeight,

为什么会有这么多属性来定位一个元素?

我觉得和盒子模型有很大关系,一个盒子就是一个区域,包含 margin、border、padding 和 content。上面 6 个属性可以非常容易定位元素。

有没有类似 iOS 中 frame 的概念?

答案是有的。可以通过 Element.getBoundingClientRect() 来确定元素在可视区域中的位置。

这些属性究竟有什么不同,我们一一分析:

1、offsetX —— 相对谁偏移了多少?

offsetX 是 HTMLElement 的只读属性,不可以修改。offset 有“偏移” 的意思,你可能会把这个属性想成与滚动有关,其实与滚动没半毛钱关系。我们先看 offsetTop 这个属性,它表示当前元素顶部到 offsetParent 节点的距离。这里关键点是 offsetParent,它是指当前元素最近的使用 position 不为 static 的祖先节点,如果没有使用 position 的祖先节点,它的值将是 body 节点(这个值有可能也是 null,如果出现这些极端情况可以查 MDN)。其实关键点是「相对谁偏移了多少的问题」。一图胜千言。

上图中,由于小人的父元素 div 是 positioned,故它的 offsetParent 为 div,而不是 body,offsetTop 是指小人顶部距离 div 距离(图中红线部分)。

同理 offsetLeft 是距离左边的距离,只要明白了 top,left 属性也就明白了。

offsetWidth 和 offsetHeight 指宽高,包含 boder 、 padding 和 content。

总之,offset 相关的属性指元素相对某个元素的位置,与滚动没有半毛钱关系。

2. scrollX —— 滚动了多少?

与 scroll 相关的属性是 Element 的属性,offsetTop、offsetLeft 可读可写,offsetWidth、offsetHeight 只读。

scroll 才真正与滚动相关,我们以竖直方向滚动为例。

只有元素可以滚动 scrollTop 才会有值,否则为 0,也就是说当子元素的高度大于父元素时,设置父元素的 overflow 为 scroll 才会生效。

当 子div 的高度超出 父div 时,父div 需要通过把 overflow 设置为 scroll,这时候 子div 才可以滚动。这里有一点需要注意,图中所标记的 scrollTop 的属性是 子div 的还是 父div 的?欢迎留言说出你的答案。

scrollTop 的值可以修改,表示在滚动区域中,竖直方向滚动了多少。通常通过修改这个值来实现让某个元素滚动到指定位置。

关于 scrollHeight 这个也需要特别留意,父 div 的 scrollHeight 是通过子div 计算的,表示可滚动的高度。

scrollWidth 与 scrollHeight 类似。我特意写了一个 demo,想要搞懂这个必须通过 demo 实践。

3. clientX  —— 我自身的位置

它是 Element 的属性。client 相关的属性描述的是自身的位置,它没有相对元素。

clientTop 就是 border-top 的值,clientLeft 就是 border-left 的值。而 clientWidth 和 clientHeight 都不包含 border。

4. Element.getBoundingClientRect() —— 相对可视区域的位置

通过这个 API 获取元素相对可视区域的位置,返回值是浮点数。其中,大多数情况下 x 与 left 相等,y 与 top 相等,只有当 width 或 height 为负数的时候会有区别。left = x + with,top = y + height。图中黄色区域为边框。

注意观察 bottom 和 right 的值。

5. 少不了 demo

我写了一个输出这些属性的方法,方便同时查看这些属性的值:

var logBySelector = function (id) {let elm = document.querySelector(id);logFrame(elm);elm.onscroll = function () {logFrame(elm);if (elm.scrollHeight - elm.scrollTop === elm.clientHeight) {console.log('到底了');}else if (elm.scrollTop === 0) {console.log('到顶了');}}
};var logFrame = function (elm) {console.log(elm, '-------------------------');console.log(elm.getBoundingClientRect());for (key in elm) {let whiteList = ['offsetTop', 'offsetLeft', 'offsetWidth', 'offsetHeight','scrollTop', 'scrollLeft', 'scrollWidth', 'scrollHeight','clientTop', 'clientLeft', 'clientWidth', 'clientHeight','offsetParent'];if (whiteList.indexOf(key) !== -1) {console.log(key, ' = ', elm[key]);}}
}

demo 地址:https://github.com/lefex/FE/tree/master/%E7%AC%AC%E4%BA%94%E9%98%B6%E6%AE%B5

本文讲解了元素相关的位置属性,这几个属性容易弄混,我特意为大家准备了 demo。这些知识与前面讲的 CSS 布局 坚持14天学懂CSS布局(领电子书),盒子模型 第10天:撑起CSS布局的半壁江山---盒子模型 有很大关系。当然我们还需要一节内容来实践一下。大家加油。


推荐阅读:

我是一颗树 · DOM

回到工位“我”悟出了 DOM 设计的精华

打通 DOM 的设计架构

两种方法轻松找到 DOM 元素

彻底搞懂 offsetX、scrollX、clientX 的区别相关推荐

  1. 一篇搞懂OOA/OOD/OOP的区别

    文章目录 OOA OOD OOP 总结 相关文章: 一篇搞懂OOA/OOD/OOP的区别 面向对象的基本原则-抽象,封装,继承,分解 GRASP模式概述 面向对象的六大原则 OOA什么鬼,OOD又是什 ...

  2. 彻底搞懂BLDC与PMSM的区别

    彻底搞懂BLDC与PMSM的区别 从结构上看 从控制上看 从应用上看 BLDC,直流无刷电机,也可以叫电子换向直流电机,反电势为梯形波,定子电流为矩形波,一般定子为集中整距绕组. PMSM,永磁同步电 ...

  3. 一文带你彻底搞懂i++和++i的区别,谁的效率更高?

    作者简介:Codebowl靓仔,学妹的工具人,C++开发误入数据开发,梦想30岁退休的靓仔就是我啦. i++和++i对于初学者来说,一直是一个特别容易搞混的内容,相信很多人现在也没有完全搞清(作者初学 ...

  4. 彻底搞懂a++和++a的区别

    a++到底做了什么操作 a++是一组操作,它的过程是这样的(假设此时a的值为10): 获取到a的值,也就是10. 进行计算,也就是把获取到的值加一,得到计算后的结果,也就是11 把计算后的结果重新赋值 ...

  5. 多图 | 搞懂volatile和synchronized的区别

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「日拱一兵」 之前写了几篇 Java并发 ...

  6. 3分钟搞懂前后端开发的区别

    上周末见了好多开发的年轻朋友,问了我一个问题:"前后端的区别和要求是什么?"分不清前后端开发的区别和要求,一种是因为前后端都了解,号称"全栈工程师",但又什么都 ...

  7. tcp udp区别优缺点_一文搞懂TCP与UDP的区别

    一.TCP协议: 位于传输层, 提供可靠的字节流服务.所谓的字节流服务(Byte Stream Service) 是指, 为了方便传输, 将大块数据分割成以报文段(segment) 为单位的数据包进行 ...

  8. udp 使用connect优点_一文搞懂TCP和UDP的区别

    TCP(Transmission Control Protocol,传输控制协议)和UDP(User Data Protocol ,用户数据报协议)都属于TCP/IP协议簇.TCP/IP协议集包括了超 ...

  9. jmeter进程和线程的区别_一文搞懂进程和线程的区别

    计算机系统是由硬件和软件组成的,它们共同协作以运行应用程序.先来看下面这张一个典型的计算机系统的硬件组成图 从上图中看出一个系统由 CPU.ALU(算术逻辑单元).PC(程序计数器).总线(贯穿整个系 ...

最新文章

  1. 跟前腾讯总监学Java实战项目
  2. Python学习系列:PyCharm CE 安装与测试
  3. 在腾讯云云函数计算上部署.NET Core 3.1
  4. 用Docker搭建Laravel和Vue项目的开发环境
  5. 围成一圈的排列组合问题_行测技巧:巧解环形排列组合
  6. CocoaPods管理iOS项目 2018年11月06日
  7. html5初探ppt,HTML5---HTML5初探151019讲义.ppt
  8. 脱口秀在尝试处理一件难事
  9. [答疑]关于产品线:充气娃娃,苍井空,猩猩
  10. 饥荒控制台输入没用_饥荒控制台怎么开启 饥荒控制台怎么用
  11. 支持GB28281协议的远程抓拍4G低功耗摄像头解决方案
  12. Hutool工具生成二维码
  13. github获取token
  14. cpu是几核的怎么查看
  15. 在 CSDN 博客 100 天技术日更的 Flag,我做到了!
  16. 实验室远程登录Linux服务器并配置环境
  17. Macbook上Gitlab下载代码
  18. Epub阅读器合集,建议收藏
  19. 日本禅师铃木俊隆的12条生活准则
  20. 基于vue的英语单词App

热门文章

  1. TVM Pass 总结
  2. Codeforces - Turn Off The TV
  3. 伯努利分布与二项分布Binomial Distribution
  4. ubuntu或Linux系统环境下安装Jupyter并成功运行
  5. 常用的lodash方法
  6. TACOS:一种用于准确预测细胞特异性长的非编码RNA亚细胞定位的新方法
  7. 冲压是一种高效率的加工方法
  8. lush的CSDN博客之旅开启了!
  9. APP测试的7大注意点。
  10. STM32嵌入式接口与传感器应用开发(1)认识嵌入式系统