HTML中各种宽高以及位置,你真的分得清楚吗?
前言
说个笑话:DOM中有一万个宽高位置类型。
在获取DOM的宽高,或者获取滚动条的位置,每一次都是想都不想直接去谷歌上找到,虽然说每次都能找到可用的,但是每次找的结果都不一样,这就很尴尬了,所以这次下决心来总结一波DOM当中到底有哪些宽高。
归类
经过系统地查阅书籍,这里总结出两大类的宽高位置:
DOM对象中的宽高位置
我们回忆之前写代码的时候,存在两种情况,第一种是获取DOM的宽高位置,第二种是设置DOM中的宽高位置,所以,我们归纳出两种宽高位置:
只读属性
- clientWidth和clientHeight
- offsetWidth和offsetHeight
- clientTop和clientLeft
- offsetLeft和offsetTop
- scrollHeight和scrollWidth
可读可写属性
- scrollTop和scrollLeft
- obj.style.*属性
Event对象中的宽高位置
这个主要是当事件触发的时候,事件触发点的位置,因此也就不存在有可读可写之分:
- clientX和clientY
- pageX和pageY
- screenX和screenY
- 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。
如图:

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算出来的。
如图:

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>
|
如图:

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>
|
如图:

这两个属性指的是当元素内部的内容超出其宽度和高度的时候,元素内部内容的实际宽度和高度,需要注意的是,当元素其中内容没有超过其高度或者宽度的时候,该属性是取不到的。
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>
|
如图:

这对属性是可读写的,指的是当元素其中的内容超出其宽高的时候,元素被滚动的高度和宽度。
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的值。
如图:

当然,因为是可写的,我们可以在初始化的时候,就设置他们的值,让他们自动滚动到某个值:
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> ...
|
如图:

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>
|
如图:

当然,我们可以直接手动去设置他们的宽高等属性:
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>
|
如图:

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>
|
如图:

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>
|
如图:

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>
|
如图;

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>
|
如图:

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