offsetLeft & offsetTop新发现

Q : 什么是offsetLeft?
A : MDN文档上阐释,HTMLElement.offsetLeft 是一个只读属性,返回当前元素左上角相对于 HTMLElement.offsetParent 节点的左边界偏移的像素值。

然而今天在测试的时候发现并非这么简单!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
html{
background: #eee;
padding: 10px;
margin: 10px;
}
body{
background: #ccc;
padding: 20px;
margin: 0;
}
#box{
background: #999;
}
</style>
</head>
<body>
<div id="box">测试</div>
</body>
<script>
var box = document.getElementById('box');
console.log(box.offsetParent); // body
console.log(box.offsetLeft); // 30
</script>
</html>

在上面这个案例中,box没有定位父级,所以box的offsetParent为body,如果说offsetLeft是相对body的左边界偏移,那么box的offsetLeft应该是20,可答案却是30。另外IE下offsetLeft为40,但现在不考虑IE,因为IE的情况太复杂。

所以可以大胆地猜测,offsetLeft是相对html的左边界偏移,而不是像MDN文档所说的那样相对于offsetParent的偏移。

同样是这个案例,如果给box设置了属性position: absolute,情况又会是什么样呢?

1
2
console.log(box.offsetParent); // body
console.log(box.offsetLeft); // 40

这让我回忆到之前在知乎上看到的:

当绝对定位元素如果没有设置定位父级,其实并不是相对于html或body定位,而是相对initial containing block定位的。initial containing block 是以整个 canvas (渲染内容的空间)的坐标原点(左上)为基准,以 viewport (也就是浏览器视窗内渲染 HTML 的空间)为大小的矩形。

这时可以大胆的猜测,对于绝对定位的元素而言,offsetLeft是相对于 “浏览器渲染内容的空间” 的左边界偏移的。

当然,一般情况下我们都会在样式重置的时候把浏览器的padding和margin设置为0,所以不会出现以上问题。

offsetLeft和offsetTop兼容性问题很多,后期若发现更规范的参考文档,再更新本篇博文。

—— end —— 注:水平有限,难免有误,如有错误欢迎指出!