offsetLeft深入研究
基础示例代码-祖先元素无定位元素
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>offsetLeft研究</title>
</head>
<body style="border: 20px solid #000;"><div id="box1" style="border: 20px solid #666; width:300px; height:300px; padding-left:20px; margin-left:20px;"><div id="box2" style="border: 20px solid #999; width:200px; height: 200px; padding-left:20px; margin-left:20px;"><div id="box3" style="border: 20px solid [[bbb]];width:100px; height: 100px; padding-left:20px; margin-left: 20px; overflow:scroll; white-space: nowrap;"><div id="box4">这里是内容区域,父级为box3,父级超出部分滚动</div></div></div></div>
</body>
<script>function clickFun(e){console.log('鼠标点击点的ClientX:', e.clientX);console.log('鼠标点击点的layerX:', e.layerX);console.log('鼠标点击点的pageX:', e.pageX);console.log('鼠标点击点的offsetX:', e.offsetX);console.log('鼠标点击点的screenX:', e.screenX);console.log('鼠标点击点的x:', e.x);console.log('box1的offsetLeft', $('box1').offsetLeft);console.log('box2的offsetLeft', $('box2').offsetLeft);console.log('box3的offsetLeft', $('box3').offsetLeft);console.log('box4的offsetLeft', $('box4').offsetLeft);}function $(id){return document.getElementById(id);}function addListener(type, fun) {if (typeof window.addEventListener != "undefined") {window.addEventListener(type, fun, false);} else {window.attachEvent('on' + type, fun)} }window.onload = function(){addListener('click', clickFun);};</script>
</html>
我们设计了实验代码结构,由body
中的四层嵌套盒子组成,除最里层的box4
外每个盒子都有20像素宽度的边框,20像素的左内边距,和20像素的左外边距。
当鼠标点击页面时,控制台输出当前点击位置的一些位置数据(只研究横向的,所以只打印横坐标值),同时打印输入四层盒子的offsetLeft
的值。
同时,box3
设计了内容宽度超出容器后显示滚动条,以便验证滚动条对offsetLeft
的影响。
先看默认状态下点击box4
的左侧边框位置后输出的结果:
将截图放大观察,得出我们的
结论1 :在祖先元素中没有定位元素时,元素的offset
值为其左边框的最左侧位置到html
页面左边框的距离值
一点引申
根据输出结果,我们还可以猜想以下两个值的意义:
offsetX
: 根据值的大小猜测为当前位置距离当前点击对象(e.target
,这里为box4
)左边框的值,至于是左边框的左侧还是右侧,需要进一步验证;
layerX
: 当前点击位置距离当前点击元素(e.target
,这里为box4
)父级元素左边框左侧的距离值
我们验证一下,这次点击box2
左边框和box3
左边框中间的位置:
可以看到,此时的offset
值为20,正好是当前点击对象(box2
)的左边框右侧位置到当前点击位置的距离。
而此时的layerX
值为148,并不是当前点击位置距离当前点击对象父级元素box1
的左边框左侧的距离值,与我们的猜想不符,我们看看MDN的说明:
The
**UIEvent.layerX**
read-only property returns the horizontal coordinate of the event relative to the current layer.
UIEvent.layerX
只读属性返回事件相对于当前层的水平坐标。This property takes scrolling of the page into account and returns a value relative to the whole of the document unless the event occurs inside a positioned element, where the returned value is relative to the top left of the positioned element.
此属性将页面滚动考虑在内,并返回一个相对于整个文档的值,除非事件发生在定位元素内,其中返回值相对于定位元素的左上角
按照该说明,这个属性返回事件相对于当前层的坐标,那么很明显,当前层并不是事件目标元素的父元素,对于层的概念,大概和盒子的渲染模型有关,没有深入研究过,鉴于这个属性并不是W3C标准属性,各个浏览器实现也没有统一标准,不再深究。
滚动的影响
为了验证滚动是否对offsetLeft
的值,我们拖动box3
的滚动条,然后同样点击box4
的左边框位置,看下结果:
可以看到,滚动条滚动后,box4
在页面上的绝对位置时改变了的,但是它(以及祖先元素)的offsetLeft
属性并没有变化,得到
结论2: 滚动区域内的内容滚动后,其offsetLeft
不受影响。
body元素定位
因为offsetLeft
是相对于其offsetParent
属性指向的元素(离它最新的定位祖先元素)的偏移量,所以必须研究当它的offsetParent
发生改变时它的值的变化。首先,为body
添加相对定位。
<body style="border: 20px solid #000; position: relative;">
使用变量控制实验法,仍旧点击box4
的左边框,看看控制台输出:
这次比我们第一次点击,位置时相同的(clientX
都是208),但是所有元素的offsetLeft
的值都少了8px,而这正好是我们第一张图中标识的body
元素左边框左侧到html
边框的距离。
这种变化是因为一开始box4
的祖先元素中没有定位元素,所以其默认定位元素时body
,但此时的offsetLeft
包含了body
的margin-left
值(在chrome
中默认为8px),而此时body
被明确定义为了定位元素,此时的offsetLeft
则不再包含body
的margin-left
值。
我们在代码中把body
的margin
值去掉,来验证下以上说法:
<body style="border: 20px solid #000; position: relative;margin:0;">
然后再看:
这里没有了margin
值,所以我们修正一下
结论1:当元素的祖先元素中没有定位元素时,offsetLeft
就是元素相对于其offsetParent
所指向的元素(body
)的左边框的左侧到元素左边框左侧的距离;
现在就有疑问了,根据offsetParent
的特征,第一张图那里offsetParent
明显也是body
元素,为什么它定位和不定位会有包含不包含margin
值的区别呢?
body取消定位,box1定位
<body style="border: 20px solid #000; margin:0;"><div id="box1" style="border: 20px solid #666; width:300px; height:300px; padding-left:20px; margin-left:20px; position: relative;">
我们取消body
元素的定位,给box1
定位,此时,根据offsetParent
的规则,box1/box2/box3
的offsetParent
应该是box1
,我们点击相同位置,看输出结果:
此时,这些值都发生了变化:
box1
当前的offsetParent
还是body
元素,所以其offsetLeft
还是它的左边框左侧到body
左边框左侧的距离(40),这个距离包含它自己的margin-left
值。box2
的offsetParent
是box1
,所以它的offsetLeft
值是它的左边框左侧到box1
左边框左侧的距离(60)减去它自己的margin-left
值(20)之后的值(40)。box3
的offsetParent
是box1
,所以它的offsetLeft
值是它的左边框左侧到box1
左边框左侧的距离(120)减去它自己的margin-left
值(20)之后的值(100)。box4
的offsetParent
是box1
,所以它的offsetLeft
是它的左边框左侧到box1
左边框左侧的距离 (160)减去 它自己的margin-left
值(20)之后的值(140)。
我们得到了
结论3:当祖先元素中有定位元素时,元素的offsetLeft
的值等于它的左边框左侧到它的offsetParent
元素左边框的距离减去它自身的margin-left
值。
元素自身为fixed定位
由于元素自身为fixed
定位时,它的offsetParent
总是为null
,那么作为一个基于offsetParent
的偏移量,元素的offsetLeft
的结果又将是什么呢?
我们修改代码,在上一个例子的基础上,将box2
的定位设为fiexd
:
<body style="border: 20px solid #000; margin:0;"><div id="box1" style="border: 20px solid #666; width:300px; height:300px; padding-left:20px; margin-left:20px; position: relative;"><div id="box2" style="border: 20px solid #999; width:200px; height: 200px; padding-left:20px; margin-left:20px; position:fixed">
再次实验:
这次的结果变化比较有意思,我们逐一分析:
此时
box1
的offsetParent
仍旧是body
元素,所以其offsetLeft
还是它的左边框左侧到body
左边框左侧的距离(40),这个距离包含它自己的margin-left
值。box2
由于其自身是fiexd
定位,我们可以看到它的offsetParent
为null
,可是它的offsetLeft
却并不为null
而是其左边框左侧到body
左边框左侧的距离,这个距离包含它自己的margin-left
值。box3
的offsetParent
此时变成离它最近的定位祖先元素box2
,它的offsetLeft
值则是它自己的左边框左侧到box2
的左边框左侧的距离,减去它自己的margin-left
值。box4
的offsetParent
此时也变成了box2
,它的offsetLeft
值是它自己的左边框左侧到box2
的左边框左侧的距离,减去它自己的margin-left
值。
我们得到
**结论4:当元素自身为fixed
定位时,它的offsetLeft
值等于它自己的左边框左侧到body
左边框左侧的距离,这个距离包含其自身的margin-left
值 **
元素自身隐藏
根据offsetParent
的规则,当元素自身的display
为none
时, 它的offsetParnt
是null
,那么它的offsetLeft
会不会发生变化呢?
我们在上一个例子的基础上将box3
的display
设置为none
:
<body style="border: 20px solid #000; margin:0;"><div id="box1" style="border: 20px solid #666; width:300px; height:300px; padding-left:20px; margin-left:20px; position: relative;"><div id="box2" style="border: 20px solid #999; width:200px; height: 200px; padding-left:20px; margin-left:20px; position: relative;"><div id="box3" style="border: 20px solid [[bbb]];width:100px; height: 100px; padding-left:20px; margin-left: 20px; overflow:scroll; white-space: nowrap; display: none;">
此时由于box3
设置为了隐藏,所以box3
和box4
在页面上不可见了,我们无法再点击box4
来进行试验,但是其实根据我们上面的试验,也同时发现,无论鼠标点击哪里,元素的offsetLeft
值不会随着鼠标点击位置的不同而变化,所以我们就随意点击页面了,看下结果:
观察后发现:
box1
与box2
的offsetLeft
仍旧遵循之前的规则box3
与box4
的offsetParent
为null
,而他们的offsetLeft
为0
我们得到
**结论5:当元素自身display
为none
时,它的offsetLeft
值为0
**
至此,关于offsetLeft
,我们得出了以下结论:
- 当元素的祖先元素中没有定位元素时,它的
offsetLeft
值等于它自己的左边框左侧到body
左边框左侧的距离,这个距离包含其自身的margin-left
值。 - 当祖先元素中有定位元素时,元素的
offsetLeft
的值等于它的左边框左侧到它的offsetParent
元素左边框的距离减去它自身的margin-left
值。 - 当元素自身为
fixed
定位时,它的offsetLeft
值等于它自己的左边框左侧到body
左边框左侧的距离,这个距离包含其自身的margin-left
值。 - 当元素自身
display
为none
时,它的offsetLeft
值为0
- 滚动区域内的内容滚动后,内容所在元素的
offsetLeft
值不受影响。
offsetLeft深入研究相关推荐
- Liferay研究-smilingleo
http://blog.csdn.net/smilingleo/article/details/1859908 Liferay研究之一:Ext环境的搭建 本篇主要介绍如何搭建Ext开发环境.网上也有很 ...
- textarea研究
前两天研究了一下textarea的直观行的换行规律,挺复杂啊: 直观行怎样取不光要看cols大小,还要看网页编码方式. cols="30"的textarea,实际上每行可以容纳29 ...
- 关于JS下offsetLeft,style.left,以及jquery中的offset().left,css(left)的区别。
最近因为工作需要,仔细研究了一下关于JS下offsetLeft,style.left,以及jquery中的offset().left,css("left")的区别. JS下的off ...
- offsetLeft,Left,clientLeft详解
背景 最近写了一个滑动条,发现自己的对offsetLeft,Left,clientLeft这几个的概念还不是很清楚,于是决定细细研究下. 分类 client部分 clientHeight:内容可视区域 ...
- 用Canvas实现刮刮卡功能的研究与实践
前几天,单位老刘让我研究一下网上最近很流行的"刮刮卡"是怎么实现的,我第一时间就想起了我媳妇曾经跟我说过的:"在HTML5中Canvas的绘图能力很强大" ...
- 2022-2028年中国安防行业研究及前瞻分析报告
[报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国安防行业市场行业相关概述.中国安防行业市 ...
- 2022-2028年中国盲盒产业研究及前瞻分析报告
[报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国盲盒行业市场行业相关概述.中国盲盒行业市 ...
- 2021-2027年中国手机结构件行业投资分析及发展战略研究咨询报告
[报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国手机结构件行业市场行业相关概述.中国手机 ...
- 2021-2027年中国手机壳行业现状研究及发展趋势分析报告
[报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国手机壳行业市场行业相关概述.中国手机壳行 ...
最新文章
- 乐意使人恐惧,源于自身的空虚
- SVM原理详细图文教程来了!一行代码自动选择核函数,还有模型实用工具
- UNIX中的文件和目录
- python【力扣LeetCode算法题库】17-电话号码的字母组合
- abap 向上取整CEIL和向下取整FLOOR
- linux shell $# $* $@ $?
- jenkins pipeline之语法篇
- 程序员伪装 AI 编程,竟骗来 2 亿的投资!
- C# 解析 Json数据
- qt开发资料下载网址
- React 之 Expected an assignment or function call and instead saw an expression 解决办法
- 打破次元壁,让游戏角色在指尖跳舞,简易的 AR 教程
- java的regex_java regex 简单使用
- mmsegmentation 训练自制数据集全过程
- 人生之路 — 成长轨迹
- 位置式PID与增量式PID区别浅析(百度百科增量式PID讲解思路概念更明确清晰)
- python打印古诗_python打印古诗_python教程:利用python基础知识取出对应诗句
- Ubuntu中如何进入recovery 模式
- 2021-2022-2 ACM集训队每周程序设计竞赛(1) - 问题 D: 点外卖 - 题解
- jeecg3.5中为dgCol标签增加自定义格式化列中的数值的功能
热门文章
- php 图片等比压缩 4M >> 400k
- 2021-08-26 网安实验-Linux操作系统加固之配置安全的linux-apache服务器
- 【伯乐在线】100个高质量Java开发者博客
- MD5数字签名算法:生成签名和验签(附代码)
- struts2之action生命周期和ActionSupport
- JavaWeb----学习(21)----struts2---ActionSupport类
- 实探华强北:芯片价格大涨背后,暴富只有几十家
- Android视频采集实时推送RTP/RTSP/RTMP
- Ubuntu 安装Flash
- 分享1个月速成软件设计师资格证的经验(●----●)