先来了解几个简单的概念
- 视口: “视口”只是实际显示文档内容的浏览器的一部分:它不包括浏览器“外壳”(如菜单、工具条和标签页)。
- 坐标分为视口坐标和文档坐标。
- document.documentElement: 返回 html 节点。
- document.body: 返回 body节点。
一、获取元素尺寸
1. el.clientWidth,el.clientHeight
content + padding
对于 <i>, <span> 这些内联元素,clientWidth 和 clientHeight 总是返回0。
2. el.offsetWidth,el.offsetHeight
content + padding + border。只读
3. el.scrollWidth,el.scrollHeight
scrollWidth = 元素内部滚动内容的宽度 + padding。
scrollWidth 的值不会受是否出现滚动条影响,即使元素设置了 overflow hidden 没有出现滚动条,值还是原来那个值。
当内容没有溢出时,这些属性与 clientWidth、clientHeight 相等。
总结:clientWidth、offsetWidth、scrollWidth 读取的都是 Layout Tree 的尺寸。
4. dom.getBoundingClientRect().width
显示到屏幕之后的尺寸。只有这个api能准确获取元素旋转等一些transform之后的宽度,另外的几个方法都不行。
下面2种方法不到万不得已不建议用:
- getComputedStyle(dom).width:获取到的是元素 content 的宽度,值会随着盒模型的改变而改变。读取的是 CSSOM 上的尺寸,不能真实的代表界面上的尺寸。
- dom.style.width:读取的是元素html上用 style="width=100px" 这样设置的尺寸,设置在css上就读取不了了。读取的是 DOM树上的尺寸。
一、元素相关
el.parentNode
返回元素的父节点。
返回第1个已定位的祖先元素。
display 为 none 的元素的 offsetParent 为 null。
el.offsetLeft, el.offsetTop
返回元素边框到 offsetParent 边框的距离。
MDN 描述是到 offsetParent 内边距的距离,这个描述不是很准确。
有无滚动条计算结果一致。有滚动条时,虽然滚动条部分看不到,但在计算 offsetLeft 时也是计算在内的。
通常需要递归计算元素到 body 的距离。
// 提示:这里忽略了计算 offsetParent 边框的宽度,如果 offsetParent 设置了边框,边框也要另外计算进去
function getElementPos(el) {
var x = 0, y = 0;
while(el != null) {
x += el.offsetLeft;
y += el.offsetTop;
el = el.offsetParent;
}
return {x, y};
}
二、滚动条相关
el.scrollLeft,el.scrollTop
滚动条滚过的距离。
el.scrollTo(x, y)
滚动条滚动到元素指定位置。
滚动到指定位置还可以用:el.scrollTop = 50。
滚动到页面顶部
export const scrollToTop = () => {
const height = document.documentElement.scrollTop || document.body.scrollTop;
if (height > 0) {
// 使用了requestAnimationFrame以后会有一个过渡效果
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, height - height / 8);
}
}
滚动到页面底部
export const scrollToBottom = () => {
window.scrollTo(0, document.body.offsetHeight);
}
el.scrollBy(x, y)
滚动条滚动一段距离。
x y 指定滚动的相对量(可以为负数)。
注意:只有在滚动条的可见属性设置为true的情况下,此方法才生效。
el.scrollIntoView()
元素滚动到可视区。
el.scrollIntoView({
behavior: 'smooth', // 平滑滚动
block: 'start', // 垂直方向上,元素滚动到视口顶部
inline: 'nearest', // 水平方向上的滚动
});
可聚焦的元素,比如 Input,focus() 方法会隐性地执行一样的“滚动到显示”操作。
三、屏幕、窗口相关
window.screen.width,window.screen.height
屏幕尺寸。
window.innerWidth,window.innerHeight
视口尺寸。
window.outerWidth,window.outerHeight
返回浏览器窗口的总高度和宽度,包括工具栏、滚动条、窗口边框等。
window.screenX, window.screenY
窗口到屏幕边界的距离。
四、获取元素坐标、尺寸的api
el.getBoundingClientRect()
返回元素相对视口的坐标(不管元素是在视口内还是视口外)。
getBoundingClientRect() 所返回的坐标都是从边框算起(不包括边框)。
getBoundingClientRect() 返回值:
{
top: 762,
bottom: 882,
left: 9,
right: 229,
width: 220,
height: 120,
x: 9,
y: 762
}
getComputedStyle(el)
返回元素的计算样式。第二个参数可选,是一个要匹配的伪元素的字符串,如 '::before','::after' 等。
计算样式的值是绝对值:类似百分比和点之类相对的单位将全部转换为绝对值。
- 获取 marginTop:不管是用 margin 还是 margin-top 设置的样式,都可以用 getComputedStyle(el).marginTop 获取,获取到的值是带 px 单位的。