彻底搞懂 offsetX、scrollX、clientX 的区别

article/2025/11/9 0:47:02

无论在 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 元素


http://chatgpt.dhexx.cn/article/vKjbS73T.shtml

相关文章

Java数组赋值时内存中的变化

java中的方法区存放的是编译后的文件 xxx.class文件当创建数组对象时,数组对象会存放在堆里面,数据也存在于堆。当给数组赋值时,方法会进栈,然后拿着数组的地址去堆里面寻找数据并赋值

Java数组:用fill()方法给数组赋值

Arrays类可以在指定位置进行数值填充,但是只能使用同一个数值进行填充: Arrays.fill(Object[] a,Object value);a表示数组,value表示填充的值 例1 public static void main(String[] args) {int[] a new int[6];//声明创建一个数组System.o…

Java数组练习--数组随机赋值

随机数生成:使用Math.random()方法,即: [ 0 , 1 ) → [ 0 , 1 ) 30 → [0 ,30) [0 ,30) 1 → [1,31) 取整后范围是[1,30] 此题目要点是,赋值之后的数组元素,要与之前赋值元素的值比较&#xff…

java 数组的创建 与 赋值

1.2.2 数组类型 基本类型的数组有3种赋值形式,如下所示: 第1种和第2种都是预先知道数组的内容,而第3种是先分配长度, 然后再给每个元素赋值。第3种形式中,即使没有给每个元素赋值,每个元素也都有一个默认值…

java 数组批量赋值_「数组赋值」java编程-定义数组并赋值 - seo实验室

数组赋值 package day03; public class TestArray { public static void main(String [] args) { int [] b; b new int[] {88,99,66}; //分步定义数组,先定义数组名,然后再为数组赋值 int [] d {88,99,100}; //直接定义数组,同时赋值 Syste…

java数组循环动态赋值_Java数组

Java语言数组遍历教程 Java语言数组遍历详解 语法 for(int i = 0;i< 数组名称.length;i++){数组名称[i]; } 说明 我们在程序中,定义了一个变量 i,用 i 的值和数组的长度值比较,因为数组的索引是从 0 开始的,所以我们遍历的数值只能够小于 数组名称.length。 数组存储的结…

Java数组的赋值机制

数组的两种赋值的方式 引用传递&#xff0c;赋的是地址 数组的值是放在JVM的堆里&#xff0c;当定义一个数组时会在JVM里的栈中&#xff0c;放置堆的地址&#xff0c;来指向JVM对应的 堆 。在对数组进行赋值的时候&#xff0c;默认情况下是引用传递&#xff0c;即把堆的地址给…

Java二维数组赋值

Java二维数组是指由多个一维数组组成的数组结构。它可以看作是一个表格&#xff0c;其中行表示数组中的第一个维度&#xff0c;列表示第二个维度。 可以使用两个方括号&#xff08;[ ] [ ]&#xff09;来声明和访问Java二维数组中的元素。 例如&#xff0c;以下代码声明了一个包…

java数组赋值_java中给数组赋值的方法

1、数组操作中&#xff0c;可以使用等于()赋值 注意&#xff1a;此时新数组只是指向原数组的存储空间&#xff0c;并没有重新申请新的空间。 实例&#xff1a;public class ArrayTest{ public static void main(String args[]){ // 1 int[] anew int[4]; a[0]1; a[1]2; a[2]3; …

Java数组变量赋值

一、问题&#xff1a;Java数组变量赋值是值传递还是址传递&#xff1f; 1.1 结论&#xff1a;java变量赋值是址传递 1.2 验证过程&#xff1a; ​ public class Test {public static void main(String[] args) {int[] arryA {1, 2, 3};int[] arryB {4, 5, 6, 7};arryA ar…

java 数组赋值_java中为数组赋值的方法

java中为数组赋值的方法 发布时间&#xff1a;2020-06-25 14:31:36 来源&#xff1a;亿速云 阅读&#xff1a;184 作者&#xff1a;Leah 这期内容当中小编将会给大家带来有关java中为数组赋值的方法&#xff0c;文章内容丰富且以专业的角度为大家分析和叙述&#xff0c;阅读完这…

【自学Java】Java语言数组赋值

Java语言数组赋值 Java数组赋值教程 在 Java 语言 中&#xff0c;给 数组 赋值&#xff0c;就相当于给每个位置上的对应的位置填充数据。 Java语言数组赋值详解 Java 中的数据赋值分为动态化赋值和静态化赋值两种赋值方式。动态化赋值指的是先定义数组&#xff0c;然后指定…

Java数组赋值数组复制(拷贝)

Java数组赋值&数组复制(拷贝) 数组赋值数组复制 1⃣️数组赋值 值传递(基本数据类型)与引用传递(数组)区别 值传递&#xff1a;基本数据类型赋值&#xff0c;赋给变量的值就是具体的数据&#xff0c;而且相互不受影响&#xff1b; int a 10; int b a; // b的变化不会影…

LATEX换行

LATEX 换行 \ newpage \maketitle 表示 begin{document} 前面的标题在这里显示 begin{document} 中的文本才显示

latex换行后(\\)如何继续缩进两格?

LaTeX 中正常换行不要使用 \&#xff0c;直接回bai车两下&#xff0c;即du在两段中间空一行&#xff0c;这样就会自动另zhi起一段并且缩dao进了。 也可以在段落前面加上 \par &#xff0c;例如 \par 第一段。\par 第二段。 就可以将它们分段了&#xff0c;如果想要在强制换行…

Latex: 表格中 自动换行居中

1、在导言区添加宏包&#xff1a; \usepackage{makecell}2、环境&#xff1a;tabular 命令&#xff1a; \makecell[居中情况]{第1行内容 \\ 第2行内容 \\ 第3行内容 ...} \makecell [c]{ResNet101\\ (11.7M)}参数说明&#xff1a; [c]是水平居中&#xff0c;[l]水平左居中&am…

.tex文件中通过空行实现LaTeX换行输出

【LaTeX换行输出代码示例】 \documentclass{article} \begin{document}Happy \TeX ing. Hello \LaTeX.Happy \TeX ing.Hello \LaTeX. \end{document} 【输出结果】

latex multirow 内换行

latex 多行合并要用到 \multirow&#xff0c; 若合并后的内容还想换行&#xff0c;就要用到其他命令了&#xff1a; 方法一&#xff1a; 使用 \shortstack 举例&#xff1a; \usepackage{booktabs} \usepackage{multirow} \begin{table}[!ht] \begin{tabular}{clrrrrrr} \…

Latex公式换行与对齐

Latex公式换行与对齐 1、引用amsmath包&#xff1a; \usepackage{amsmath}2、公式中用aligned&#xff1a; \begin{equation} \begin{aligned} ...... \end{aligned} \end{equation}或者直接用align&#xff1a; \begin{align} ...... \end{align}3、换行时用“\”换行符 …

Latex长公式换行符号对齐

实现如图效果&#xff1a; Latex如下&#xff1a; \begin{equation} \begin{cases} \begin{aligned} x&12345 \\ &\quad 67 \\ y&123 \\ z&92 \end{aligned} \end{cases} \end{equation}\begin{equation} ... \end{equation} 创建公式环境\begin{cases} ... \…