HTML中各种宽高以及位置,你真的分得清楚吗?

前言

说个笑话:DOM中有一万个宽高位置类型。

在获取DOM的宽高,或者获取滚动条的位置,每一次都是想都不想直接去谷歌上找到,虽然说每次都能找到可用的,但是每次找的结果都不一样,这就很尴尬了,所以这次下决心来总结一波DOM当中到底有哪些宽高。

归类

经过系统地查阅书籍,这里总结出两大类的宽高位置:

DOM对象中的宽高位置

我们回忆之前写代码的时候,存在两种情况,第一种是获取DOM的宽高位置,第二种是设置DOM中的宽高位置,所以,我们归纳出两种宽高位置:

只读属性

  1. clientWidth和clientHeight
  2. offsetWidth和offsetHeight
  3. clientTop和clientLeft
  4. offsetLeft和offsetTop
  5. scrollHeight和scrollWidth

可读可写属性

  1. scrollTop和scrollLeft
  2. obj.style.*属性

Event对象中的宽高位置

这个主要是当事件触发的时候,事件触发点的位置,因此也就不存在有可读可写之分:

  1. clientX和clientY
  2. pageX和pageY
  3. screenX和screenY
  4. offsetX和offsetY

列出了以上我们常用的宽高位置属性,我们下面就开始一一讲解他的概念以及常见用法。

DOM对象中

只读属性指的是DOM节点的固有属性,该属性只能获取而不能设置,而且获取的值是只有数字并不带单位的,默认单位为px,其他单位也将转换为px,而可写属性,则方便我们用Js来控制DOM的位置。

clientWidth和clientHeight

该属性指的是元素的可视部分宽度和高度,即 padding + content ,如果没有滚动条,即为元素设定的高度和宽度,如果出现滚动条,滚动条会遮盖元素的宽高,那么该属性就是其本来宽高减去滚动条的宽高,滚动条出现的以否,还取决的浏览器的种类和环境,比如在 mac 系统下的chorme,初始状态下是不会出现滚动条的,所以也不会减去滚动条的宽高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<style>
.container {
width: 100px;
height: 300px;
border: 1px solid red;
overflow: auto;
}
</style>
<body>
<div class="container">
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
</div>
</body>
<script>
window.onload=function(){
const ele=document.getElementById("test");
console.log(ele.clientWidth+":"+ele.clientHeight);
}
</script>

这里我们设置元素的宽高为 100300 ,因为在mac系统下的chorme,初始不现实滚动条,所以还是可视部分宽高的 100300。

如图:

image

offsetWidth和offsetHeight

这一对属性指的是元素的border+padding+content的宽度和高度,该属性和其内部的内容是否超出元素大小无关,只和本来设定的border以及width和height有关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<style>
.container {
width: 300px;
height: 100px;
border: 15px solid red;
overflow: auto;
}
</style>
<body>
<div id="test" class="container">
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
</div>
</body>
<script>
window.onload=function(){
const ele=document.getElementById("test");
console.log(ele.offsetWidth+":"+ele.offsetHeight);
}
</script>

这里我们设置了15px的border,突出offsetWidth是由原本border+padding+content算出来的。

如图:

image

clientTop和clientLeft

这个很简单,只是用来读取元素的border的宽度和高度的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<style>
.container {
width: 300px;
height: 100px;
border: 15px solid red;
overflow: auto;
}
</style>
<body>
<div id="test" class="container">
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
<p>Nice to meet you!</p>
</div>
</body>
<script>
window.onload=function(){
const ele=document.getElementById("test");
console.log(ele.clientLeft+":"+ele.clientTop);
}
</script>

如图:

image

offsetLeft和offsetTop

offsetLeft和offsetTop指的是当前元素,相对于其离自己最近的具有定位的(position:absolute或者position:relative)父级元素左边距离和上边距离,即当前元素的border到包含它的父元素的border的距离如下所示:

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
<style>
.container {
position: relative;
width: 300px;
height: 300px;
border: 25px solid red;
}
.box {
position: absolute;
left: 100px;
top: 100px;
width: 100px;
height: 100px;
border: 20px solid blue;
}
</style>
<body>
<div id="test" class="container">
<div id="box1" class="box"></div>
</div>
</body>
<script>
window.onload=function(){
const ele=document.getElementById("box1");
console.log(ele.offsetLeft+":"+ele.offsetTop);
}
</script>

如图:

image

scrollHeight和scrollWidth

这两个属性指的是当元素内部的内容超出其宽度和高度的时候,元素内部内容的实际宽度和高度,需要注意的是,当元素其中内容没有超过其高度或者宽度的时候,该属性是取不到的。

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
<style>
.container {
width: 300px;
height: 100px;
border: 5px solid red;
}
p {
background: pink;
}
</style>
<body>
<div id="test" class="container">
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
</div>
</body>
<script>
window.onload=function(){
const ele=document.getElementById("test");
console.log(ele.scrollHeight+":"+ele.scrollWidth);
}
</script>

如图:

image

scrollTop和scrollLeft

这对属性是可读写的,指的是当元素其中的内容超出其宽高的时候,元素被滚动的高度和宽度。

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
<style>
.container {
width: 300px;
height: 100px;
border: 5px solid red;
overflow: auto;
}
p {
background: pink;
width: 500px;
}
</style>
<body>
<div id="test" class="container">
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
</div>
</body>
<script>
const ele=document.getElementById("test");
ele.onscroll=function(){
console.log(this.scrollTop+":"+this.scrollLeft);
}
</script>

这里,当我们滚动内容的时候,就会发现滚动了多少值,就是scrollTop和scrollLeft的值。

如图:

image

当然,因为是可写的,我们可以在初始化的时候,就设置他们的值,让他们自动滚动到某个值:

1
2
3
4
5
6
7
8
...
<script>
const ele=document.getElementById("test");
ele.scrollTop=20;
ele.scrollLeft=50;
console.log(ele.scrollTop+":"+ele.scrollLeft);
</script>
...

如图:

image

obj.style.*属性

对于一个dom元素,它的style属性返回的是一个对象,这个对象中的任意一个属性是可读写的。在读的时候,他们返回的值常常是带有单位的(如px),同时,对于这种方式,获取到的只是他的行内样式,也即是说我们设置的内嵌样式是读取不到的。

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
<style>
.container {
width: 300px;
height: 100px;
border: 5px solid red;
overflow: auto;
}
p {
background: pink;
width: 500px;
}
</style>
<body>
<div id="test" class="container" style="margin: 30px">
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
<p>Nice to meet you</p>
</div>
</body>
<script>
const ele=document.getElementById("test");
console.log(ele.style);
</script>

如图:

image

当然,我们可以直接手动去设置他们的宽高等属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<style>
.container {
width: 300px;
height: 100px;
border: 5px solid red;
}
</style>
<body>
<div id="test" class="container" style="margin: 30px">test</div>
<button id="btn"> submit </button>
</body>
<script>
let ele=document.getElementById("test");
let btn = document.getElementById("btn");
btn.addEventListener('click', function(){
ele.style.color = "red";
}, false);
</script>

如图:

image

Event对象中

clientX和clientY

当事件触发时,鼠标点击位置相对于浏览器(可视区)的坐标,即浏览器左上角坐标的(0,0),该属性以浏览器左上角坐标为原点,计算鼠标点击位置距离其左上角的位置。

1
2
3
4
5
6
7
8
9
10
11
<body>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
</body>
<script>
const body=document.querySelector('body');
body.onclick=function(ev){ const evt=ev||event; console.log(evt.clientX+":"+evt.clientY); }
</script>

如图:

image

pageX和pageY

该属性是事件发生时鼠标点击位置相对于页面的位置,通常浏览器窗口没有出现滚动条时,该属性和event.clientX及event.clientY是等价的,但是当浏览器出现滚动条的时候,pageX通常会大于clientX,因为页面还存在被卷起来的部分的宽度和高度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
.test {
width: 100px;
height: 500px;
background: pink;
}
</style>
<body>
<div class="test"></div>
</body>
<script>
const body=document.querySelector('.test');
body.onclick=function(ev){ const evt=ev||event; console.log(evt.pageX+":"+evt.pageY); }
</script>

如图:

image

screenX和screenY

事件发生时鼠标相对于屏幕的坐标,以设备屏幕的左上角为原点,事件发生时鼠标点击的地方即为该点的screenX和screenY值:

1
2
3
4
5
6
7
8
9
10
11
<body>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
<h1>Nice to meet you</h1>
</body>
<script>
const body=document.querySelector('body');
body.onclick=function(ev){ const evt=ev||event; console.log(evt.screenX+":"+evt.screenY); }
</script>

如图;

image

offsetX和offsetY

这一对属性是指当事件发生时,鼠标点击位置相对于该事件源的位置,即点击该div,以该div左上角为原点来计算鼠标点击位置的坐标,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
.test {
position: absolute;
left: 80px;
top: 120px;
width: 100px;
height: 100px;
background: pink;
}
</style>
<body>
<div class="test"></div>
</body>
<script>
const body=document.querySelector('.test');
body.onclick=function(ev){ const evt=ev||event; console.log(evt.offsetX+":"+evt.offsetY); }
</script>

如图:

image

Last

这篇长文我们列出了常用的DOM和事件的位置宽高,下次工作中再遇到需要使用获取宽高位置,再也不用一头扎进谷歌中找半天才找到合适的,直接在文章中查找,这也是我写博客的重要目的之一,有时候以前学过的东西会忘记,下次再要用到的时候,经常会记不起来,这个时候,如果之前有笔记,那么就能快速的查阅复习到。

Time tames the strongest grief. :)