基础示例代码-祖先元素无定位元素

<!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包含了bodymargin-left值(在chrome中默认为8px),而此时body被明确定义为了定位元素,此时的offsetLeft则不再包含bodymargin-left值。

我们在代码中把bodymargin值去掉,来验证下以上说法:

<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/box3offsetParent应该是box1,我们点击相同位置,看输出结果:

此时,这些值都发生了变化:

  • box1当前的offsetParent还是body元素,所以其offsetLeft还是它的左边框左侧到body左边框左侧的距离(40),这个距离包含它自己的margin-left值。
  • box2offsetParentbox1,所以它的offsetLeft值是它的左边框左侧到box1左边框左侧的距离(60)减去它自己的margin-left值(20)之后的值(40)。
  • box3offsetParentbox1,所以它的offsetLeft值是它的左边框左侧到box1左边框左侧的距离(120)减去它自己的margin-left值(20)之后的值(100)。
  • box4offsetParentbox1,所以它的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">

再次实验:

这次的结果变化比较有意思,我们逐一分析:

  • 此时 box1offsetParent仍旧是 body元素,所以其offsetLeft还是它的左边框左侧到body左边框左侧的距离(40),这个距离包含它自己的margin-left值。

  • box2由于其自身是fiexd 定位,我们可以看到它的offsetParentnull,可是它的offsetLeft却并不为null 而是其左边框左侧到body左边框左侧的距离,这个距离包含它自己的margin-left值。

  • box3offsetParent此时变成离它最近的定位祖先元素box2,它的offsetLeft值则是它自己的左边框左侧到

    box2的左边框左侧的距离,减去它自己的margin-left值。

  • box4offsetParent 此时也变成了 box2,它的offsetLeft值是它自己的左边框左侧到box2的左边框左侧的距离,减去它自己的margin-left值。

我们得到

**结论4:当元素自身为fixed定位时,它的offsetLeft值等于它自己的左边框左侧到body左边框左侧的距离,这个距离包含其自身的margin-left值 **

元素自身隐藏

根据offsetParent的规则,当元素自身的displaynone时, 它的offsetParntnull,那么它的offsetLeft会不会发生变化呢?

我们在上一个例子的基础上将box3display设置为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 设置为了隐藏,所以box3box4在页面上不可见了,我们无法再点击box4来进行试验,但是其实根据我们上面的试验,也同时发现,无论鼠标点击哪里,元素的offsetLeft值不会随着鼠标点击位置的不同而变化,所以我们就随意点击页面了,看下结果:

观察后发现:

  • box1box2offsetLeft仍旧遵循之前的规则
  • box3box4offsetParentnull ,而他们的offsetLeft为0

我们得到

**结论5:当元素自身displaynone时,它的offsetLeft值为0 **

至此,关于offsetLeft,我们得出了以下结论:

  • 当元素的祖先元素中没有定位元素时,它的offsetLeft值等于它自己的左边框左侧到body左边框左侧的距离,这个距离包含其自身的margin-left值。
  • 当祖先元素中有定位元素时,元素的offsetLeft的值等于它的左边框左侧到它的offsetParent元素左边框的距离减去它自身的margin-left值。
  • 当元素自身为fixed定位时,它的offsetLeft值等于它自己的左边框左侧到body左边框左侧的距离,这个距离包含其自身的margin-left值。
  • 当元素自身displaynone时,它的offsetLeft值为0
  • 滚动区域内的内容滚动后,内容所在元素的offsetLeft值不受影响。

offsetLeft深入研究相关推荐

  1. Liferay研究-smilingleo

    http://blog.csdn.net/smilingleo/article/details/1859908 Liferay研究之一:Ext环境的搭建 本篇主要介绍如何搭建Ext开发环境.网上也有很 ...

  2. textarea研究

    前两天研究了一下textarea的直观行的换行规律,挺复杂啊: 直观行怎样取不光要看cols大小,还要看网页编码方式. cols="30"的textarea,实际上每行可以容纳29 ...

  3. 关于JS下offsetLeft,style.left,以及jquery中的offset().left,css(left)的区别。

    最近因为工作需要,仔细研究了一下关于JS下offsetLeft,style.left,以及jquery中的offset().left,css("left")的区别. JS下的off ...

  4. offsetLeft,Left,clientLeft详解

    背景 最近写了一个滑动条,发现自己的对offsetLeft,Left,clientLeft这几个的概念还不是很清楚,于是决定细细研究下. 分类 client部分 clientHeight:内容可视区域 ...

  5. 用Canvas实现刮刮卡功能的研究与实践

        前几天,单位老刘让我研究一下网上最近很流行的"刮刮卡"是怎么实现的,我第一时间就想起了我媳妇曾经跟我说过的:"在HTML5中Canvas的绘图能力很强大" ...

  6. 2022-2028年中国安防行业研究及前瞻分析报告

    [报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国安防行业市场行业相关概述.中国安防行业市 ...

  7. 2022-2028年中国盲盒产业研究及前瞻分析报告

    [报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国盲盒行业市场行业相关概述.中国盲盒行业市 ...

  8. 2021-2027年中国手机结构件行业投资分析及发展战略研究咨询报告

    [报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国手机结构件行业市场行业相关概述.中国手机 ...

  9. 2021-2027年中国手机壳行业现状研究及发展趋势分析报告

    [报告类型]产业研究 [报告价格]4500起 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中国手机壳行业市场行业相关概述.中国手机壳行 ...

最新文章

  1. 乐意使人恐惧,源于自身的空虚
  2. SVM原理详细图文教程来了!一行代码自动选择核函数,还有模型实用工具
  3. UNIX中的文件和目录
  4. python【力扣LeetCode算法题库】17-电话号码的字母组合
  5. abap 向上取整CEIL和向下取整FLOOR
  6. linux shell $# $* $@ $?
  7. jenkins pipeline之语法篇
  8. 程序员伪装 AI 编程,竟骗来 2 亿的投资!
  9. C# 解析 Json数据
  10. qt开发资料下载网址
  11. React 之 Expected an assignment or function call and instead saw an expression 解决办法
  12. 打破次元壁,让游戏角色在指尖跳舞,简易的 AR 教程
  13. java的regex_java regex 简单使用
  14. mmsegmentation 训练自制数据集全过程
  15. 人生之路 — 成长轨迹
  16. 位置式PID与增量式PID区别浅析(百度百科增量式PID讲解思路概念更明确清晰)
  17. python打印古诗_python打印古诗_python教程:利用python基础知识取出对应诗句
  18. Ubuntu中如何进入recovery 模式
  19. 2021-2022-2 ACM集训队每周程序设计竞赛(1) - 问题 D: 点外卖 - 题解
  20. jeecg3.5中为dgCol标签增加自定义格式化列中的数值的功能

热门文章

  1. php 图片等比压缩 4M >> 400k
  2. 2021-08-26 网安实验-Linux操作系统加固之配置安全的linux-apache服务器
  3. 【伯乐在线】100个高质量Java开发者博客
  4. MD5数字签名算法:生成签名和验签(附代码)
  5. struts2之action生命周期和ActionSupport
  6. JavaWeb----学习(21)----struts2---ActionSupport类
  7. 实探华强北:芯片价格大涨背后,暴富只有几十家
  8. Android视频采集实时推送RTP/RTSP/RTMP
  9. Ubuntu 安装Flash
  10. 分享1个月速成软件设计师资格证的经验(●----●)