HTML和位置相关的属性

HTML

img

client

图片描述

其中

  • clientHeight:内容可视区域的高度,也就是说页面浏览器中可看到内容区域的高度(不含边框,也不含滚动条)。
  • clientLeft/clientTop: 就是边框的宽度,如果不指定一个边框,值就是0.

clientWidth

属性表示元素的内部宽度,以像素计。该属性包括内边距,但不包括垂直滚动条(如果有)、边框和外边距。

如上图所示, 计算方式为, 分为如下两种:

  • 存在垂直滚动条

    content width + padding - scollbarWidth

  • 不存在滚动条

    content width + padding

clientHeight

属性表示元素内部的高度(单位像素),包含内边距,但不包括水平滚动条、边框和外边距。

如上图所示, 计算方式为如下两种:

  • 存在水平滚动条

    content height + padding - scollbarWidth

  • 不存在滚动条

    content height + padding

clientLeft

表示一个元素的左边框的宽度.

计算方式为如下两种情况:

  • 如果文字方向从右往左(默认从左往右,通过设置 direction: rtl;)进行排列,且存在垂直滚动条的情况下

    border width + scollbar width

  • 默认情况下

    border width

注意:

如果当前元素是行内元素(inline)时, clientLeft将返回 0;

计算滚动条宽度

1
2
3
4
5
6
7
8
9
// 默认情况下(没有滚动条情况下) 
clientWidth = content width + paddingLeftWidth + paddingRightWidth;
// 对上面示例来说 clientWidth = 200 + 10 + 10;

// 有滚动条情况下:
clientWidth = (content width + paddingLeftWidth + paddingRightWidth) - scrollbarWidth

// 可以推断出滚动条计算方式:
scrollbarWidth = (content width + paddingLeftWidth + paddingRightWidth) - clientWidth;

offset

计算时都包括此对象的border,padding

获取对象到父级的距离取决于最近的定位父级

20220720142621

其中

  • offsetWidth:获取元素自身的宽度(包含边框)
  • offsetHeight:获取元素自身的高度(包含边框)
  • offsetLeft:获取对象左侧与定位父级之间的距离
  • offsetTop:获取对象上侧与定位父级之间的距离

offsetLeft 返回值包含:

  • 本元素向左偏移的像素值,元素的外边距(margin)
  • offset父元素的左侧内边距(padding)

注意

offset父元素 不是父元素 是一直向外找的第一个有定位的元素。

注:

与style.top 不同,offsetLeft只可读,不可以对其进行赋值。

offsetTop 返回的是数字,而 style.top 返回的是字符串,除了数字外还带有单位:px。
与style.width属性的区别在于:如对象的宽度设定值为百分比宽度,则无论页面变大还是变小,style.width都返回此百分比,而offsetWidth则返回在不同页面中对象的宽度值而不是百分比值

比如这个例子

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>offset</title>
</head>

<body>

<div class="div1">
<div class="div2"></div>
</div>

<style>
body {
margin: 0;
padding: 0;
}

.div1 {
position: relative;
width: 200px;
height: 200px;
background-color: burlywood;
margin: 64px;
border: 32px solid black;
padding: 16px;
}

.div2 {
position: relative;
width: 100px;
height: 100px;
background-color: rgb(127, 165, 219);
margin: 8px;
border: 4px solid black;
padding: 2px;
}
</style>

<script>
let div2 = document.querySelector(".div2");
console.info(div2.offsetLeft);
console.info(div2.offsetParent)
</script>
</body>

</html>

获取到的div2.offsetLeft就是24,为div2的margin+div1的padding

谷歌、Edge、火狐、IE均是如此。

scroll

其中:

  • scrollLeft:设置或获取当前左滚的距离,即左卷的距离;
  • scrollTop:设置或获取当前上滚的距离,即上卷的距离;
  • scrollHeight:获取对象可滚动的总高度;
  • scrollWidth:获取对象可滚动的总宽度;
  • scrollHeight = content + padding;(即border之内的内容)

getBoundingClientRect

Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。

该对象使用 lefttoprightbottomxywidthheight 这几个以像素为单位的只读属性描述整个矩形的位置和大小。

除了 widthheight 以外的属性是相对于视图窗口的左上角来计算的。

img

Event中的clientX和offsetX

event.clientX 和 event.offsetX 都是用来获取鼠标事件位置的属性,但有以下区别:

  • event.clientX: 鼠标相对于浏览器窗口的X坐标。
  • event.offsetX: 鼠标相对于事件元素的X坐标。

举个例子:

1
2
3
<div id="container" style="position: relative; left: 100px;">
<button id="button">Click me</button>
</div>

JS

1
2
3
4
5
6
7
8
9
const button = document.getElementById('button');

button.addEventListener('click', (event) => {
// 鼠标相对浏览器窗口左侧的x坐标
console.log(event.clientX);

// 鼠标相对按钮左侧的x坐标
console.log(event.offsetX);
});

当点击按钮时:

  • event.clientX 将会是鼠标相对浏览器窗口左侧的距离
  • event.offsetX 将会是鼠标相对按钮左侧的距离

因为按钮在一个设置了left的div内,所以两者的值会有差异。
综上,如果要获取相对于元素自身的鼠标位置,应该使用 offsetX 和 offsetY。

如果要页面绝对位置,应该使用 clientX 和 clientY。

获取DIV坐标

绝对位置

网页元素的绝对位置,指该元素的左上角相对于整张网页左上角的坐标

首先,每个元素都有offsetTop和offsetLeft属性,表示该元素的左上角与父容器(offsetParent对象)左上角的距离。所以,只需要将这两个值进行累加,就可以得到该元素的绝对坐标。

但这里要注意一个问题:要考虑offsetParent的border的宽度。

方式1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 得到对象的相对浏览器的坐标
export function getObjPos(_target) {
var target = _target;
var pos = {
x: target.offsetLeft,
y: target.offsetTop
};

target = target.offsetParent;
while (target) {
pos.x += target.offsetLeft + target.clientLeft;
pos.y += target.offsetTop + target.clientTop;

target = target.offsetParent
}
return pos;
}

注意

一定要添加父元素的Border的宽度(clientLeft)。

隐藏的元素要用opacity: 0;,不能用display: none;,否则获取不了位置。

这种方式不是特别精确,如果dom的宽高不是整数的时候会出现偏差。

运算效率也相对较低。

方式2

这种方式要注意滚动条所在的DOM是那个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export function getObjPos(_target, scroll_dom) {
var rect = _target.getBoundingClientRect();
var pos = {
x: rect.left,
y: rect.top
};
var scrollLeft = 0;
var scrollTop = 0;
if (scroll_dom) {
scrollLeft = scroll_dom.scrollLeft;
scrollTop = scroll_dom.scrollTop;
} else {
scrollLeft =
document.body.scrollLeft || document.documentElement.scrollLeft;
scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
}

pos.x += scrollLeft;
pos.y += scrollTop;
return pos;
}

注意

隐藏的元素要用opacity: 0;,不能用display: none;,否则获取不了位置。

运算效率相对高点。

相对位置

网页元素的相对位置,指该元素左上角相对于浏览器窗口左上角的坐标

方法1

获取元素的相对位置,JS还提供了一种更简单的方法:Element.getBoundingClientRect()

Element.getBoundingClientRect()返回一个对象,对象包含了元素距离窗口的位置属性:left、right、top、bottom

1
2
3
let odiv = document.querySelector(".div2");
console.info(odiv.getBoundingClientRect().left);
console.info(odiv.getBoundingClientRect().top);

方法2

有了绝对位置以后,获得相对位置就很容易了,只要将绝对坐标减去页面的滚动条滚动的距离就可以了。

1
2
3
4
5
6
7
8
function getObjPosR (element) {
let pos = getObjPos2(element);
var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft;
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
pos.x -= scrollLeft;
pos.y -= scrollTop;
return pos;
}