彻底搞懂 offsetX、scrollX、clientX 的区别
无论在 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 的区别相关推荐
- 一篇搞懂OOA/OOD/OOP的区别
文章目录 OOA OOD OOP 总结 相关文章: 一篇搞懂OOA/OOD/OOP的区别 面向对象的基本原则-抽象,封装,继承,分解 GRASP模式概述 面向对象的六大原则 OOA什么鬼,OOD又是什 ...
- 彻底搞懂BLDC与PMSM的区别
彻底搞懂BLDC与PMSM的区别 从结构上看 从控制上看 从应用上看 BLDC,直流无刷电机,也可以叫电子换向直流电机,反电势为梯形波,定子电流为矩形波,一般定子为集中整距绕组. PMSM,永磁同步电 ...
- 一文带你彻底搞懂i++和++i的区别,谁的效率更高?
作者简介:Codebowl靓仔,学妹的工具人,C++开发误入数据开发,梦想30岁退休的靓仔就是我啦. i++和++i对于初学者来说,一直是一个特别容易搞混的内容,相信很多人现在也没有完全搞清(作者初学 ...
- 彻底搞懂a++和++a的区别
a++到底做了什么操作 a++是一组操作,它的过程是这样的(假设此时a的值为10): 获取到a的值,也就是10. 进行计算,也就是把获取到的值加一,得到计算后的结果,也就是11 把计算后的结果重新赋值 ...
- 多图 | 搞懂volatile和synchronized的区别
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「日拱一兵」 之前写了几篇 Java并发 ...
- 3分钟搞懂前后端开发的区别
上周末见了好多开发的年轻朋友,问了我一个问题:"前后端的区别和要求是什么?"分不清前后端开发的区别和要求,一种是因为前后端都了解,号称"全栈工程师",但又什么都 ...
- tcp udp区别优缺点_一文搞懂TCP与UDP的区别
一.TCP协议: 位于传输层, 提供可靠的字节流服务.所谓的字节流服务(Byte Stream Service) 是指, 为了方便传输, 将大块数据分割成以报文段(segment) 为单位的数据包进行 ...
- udp 使用connect优点_一文搞懂TCP和UDP的区别
TCP(Transmission Control Protocol,传输控制协议)和UDP(User Data Protocol ,用户数据报协议)都属于TCP/IP协议簇.TCP/IP协议集包括了超 ...
- jmeter进程和线程的区别_一文搞懂进程和线程的区别
计算机系统是由硬件和软件组成的,它们共同协作以运行应用程序.先来看下面这张一个典型的计算机系统的硬件组成图 从上图中看出一个系统由 CPU.ALU(算术逻辑单元).PC(程序计数器).总线(贯穿整个系 ...
最新文章
- 跟前腾讯总监学Java实战项目
- Python学习系列:PyCharm CE 安装与测试
- 在腾讯云云函数计算上部署.NET Core 3.1
- 用Docker搭建Laravel和Vue项目的开发环境
- 围成一圈的排列组合问题_行测技巧:巧解环形排列组合
- CocoaPods管理iOS项目 2018年11月06日
- html5初探ppt,HTML5---HTML5初探151019讲义.ppt
- 脱口秀在尝试处理一件难事
- [答疑]关于产品线:充气娃娃,苍井空,猩猩
- 饥荒控制台输入没用_饥荒控制台怎么开启 饥荒控制台怎么用
- 支持GB28281协议的远程抓拍4G低功耗摄像头解决方案
- Hutool工具生成二维码
- github获取token
- cpu是几核的怎么查看
- 在 CSDN 博客 100 天技术日更的 Flag,我做到了!
- 实验室远程登录Linux服务器并配置环境
- Macbook上Gitlab下载代码
- Epub阅读器合集,建议收藏
- 日本禅师铃木俊隆的12条生活准则
- 基于vue的英语单词App