js中的各种距离
js中各种距离很容易混淆,再加上各种兼容问题,非常容易出错。
style.width/height
::: tip 提示
- style.width/height只能获取内联样式中的宽高,
- style.width/height=content,不包含margin、padding、border的。
- style.width/height获取的值是
string
,并且带单位px(em,rem)。 :::<style> #box1{ width:20px; height:20x; } </style> <div id="box1" style="width:10em;height:100px;margin:10px;padding:10px;border:1px solid #ddd;"></div> <script> var box1=document.getElementById('box1') console.log(box1.style.width,box1.style.height)//100px,100px </script>
clientWidth/clientHeight
::: tip 注意 - clientWidth/clientHeight获取的是可视区域的宽高,包括屏幕和dom元素的可视区域。
- clientWidth/clientHeight=content+padding ,如果有滚动条,不包括滚动条
- 常规方式window.innerWidth/innerHeight,IE9/IE8及以下:怪异模式,document.body.clientWidth/clientHeight,标准模式,document.documentElement.clientWidth/clientHeight
- 在怪异模式下,
document.body.clientWidth/clientHeight
和document.documentElement.clientWidth/clientHeight
都能获取到正确的值,但是在标准模式下document.body.clientHeight
获取的值<mark>不准确</mark>,document.body.clientWidth
和document.documentElement.clientWidth/clientHeight
都能获取到正确的值。 - clientWidth/clientHeight获取到的值是
number
,没有单位 :::// 获取可视区域的宽高 function getViewportSize(){ if(window.innerWidth){ return { width:window.innerWidth, height:window.innerHeight } }else{ // 这里是不能用||运算符的 if(document.compatMode==="BackCompat"){ // 怪异模式 return { width:document.body.clientWidth, height:document.body.clientHeight } }else{ // 标准模式 return { width:document.documentElement.clientWidth, height:document.documentElement.clientHeight } } }
}
## offsetWidth/offsetHeight
::: tip 注意
+ offsetWidth/offsetHeight获取的是元素的实际宽高。
+ offsetWidth/offsetHeight=content+padding+border+滚动条
+ 如果有滚动条,包括滚动条(比如div宽度100,在有垂直滚动条的时候,获取的offsetWidth=83,因为滚动条的默认宽度为17)
+ 在没有滚动条的时候,offsetWidth/offsetHeight和clientWidth/clientHeight获取的值相等
:::
```js
// 获取元素的宽高
function getOffsetSize(){
return {
width:document.body.offsetWidth,
height:document.body.offsetHeight
}
}
scrollWidth/scrollHeight
::: tip 注意
- scrollWidth/scrollHeight获取的是实际内容的宽高,比如div盒子的宽度高度是100px,里面内容高度是200px,这个时候会出现垂直滚动条,scrollHeight=200
- scrollWidth/scrollHeight=content+padding
- 如果有滚动条,不包括滚动 :::
<style type="text/css">
*{
margin:0;
padding:0;
}
#box1{
width: 100px;
height: 100px;
padding: 20px;
margin: 20px;
border:2px solid #333;
background: red;
overflow: auto;
}
#box2{
width: 50px;
height: 500px;
padding: 10px;
margin:10px;
border:1px solid #ddd;
background: green;
}
</style>
<body>
<div id="box1">
<div id="box2"></div>
</div>
<script type="text/javascript">
var box1=document.getElementById('box1')
var box2=document.getElementById('box2')
console.log(box1.scrollWidth)//100+20*2-17=123
console.log(box1.scrollHeight)//20*2+500+10*2+10*2+1*2=582
console.log(box2.scrollWidth)//50+10*2=70
console.log(box2.scrollHeight)//500+10*2=520
</script>
</body>
getBoundingClientRect()
::: tip 注意
- getBoundingClientRect()获取的是元素的宽度和上下左右的距离集合。
- getBoundingClientRect()获取的值可能带小数,在某些情况下要特别注意。
- 上面都是通过属性来获取宽高的,getBoundingClientRect()是通过方法获取的。
- getBoundingClientRect.width/height=content+padding+border
- getBoundingClientRectwidth/height和offsetWidth/height相同 :::
console.log(box1.getBoundingClientRect())
// 获取的结果为
// {bottom: 164
// height: 144
// left: 20
// right: 164
// top: 20
// width: 144
// x: 20
// y: 20}
scrollTop/scrollLeft
::: tip 注意
- scrollTop/scrollLeft 获取滚动条向上/向左滚动的距离
- 获取滚动距离的方式有很多,常规方式 window.pageYOffset/pageXOffset ,IE9及IE8以下,document.body.scrollTop/scrollLeft或者document.documentElement.scrollTop/scrollLeft,不常规的方式 window.scrollY/scrollX
- 在怪异模式下,document.documentElement.scrollTop=0,在标准模式下,document.body.scrollTop=0 :::
// 获取滚动条的滚动距离
function getScrollOffset(){
if(window.pageYOffset){
return {
top:window.pageYOffset,
left:window.pageXOffset
}
}else{
return {
// 因为这两种方式是互斥的,所以这里使用||或者+都可以
top:document.body.scrollTop||document.documentElement.scrollTop,
left:document.body.scrollLeft||document.documentElement.scrollLeft
}
}
}
offsetTop/offsetLeft
::: tip 注意
- offsetTop/offsetLeft获取当前元素到父级元素上边和左边的距离
- 如果所有父级元素都没有使用定位(relative,absolute,fixed),offsetTop/offsetLeft就是到页面顶部的距离
- 如果父级元素使用了定位,offsetTop/offsetLeft获取到的就是当前元素到父级元素直接的距离 :::
案例说明
::: danger 注意 在上面的例子中,大部分都是获取网页的宽高,就会存在window、document.body、document.documentElement这样的写法,如果是获取某个元素el的宽高,直接el.clientWidth、el.scrollWidth、el.offsetWidth这样写就行了。 :::
总结
- 上面获取到的宽高都不包括margin值,(在有滚动条的时候,获取父元素的scrollWidth/scrollHeight时,子元素的内容要加子元素margin值)
- style.width/height基本很少使用,因为很少地方会写行内样式
- offsetTop/offsetLeft获取的距离跟父元素的定位方式有关,如果要获取元素距离页面顶部和左边的距离,使用getBoundingClientRect()会更方便
- clientWidth/clientHeight=content+padding; scrollWidth/scrollHeight=content+padding; offsetWidth/offsetHeight=content+padding+border;