offset 系列
获取位置
获取元素距离父元素左上角的距离.
注意, 以带有定位的父亲元素为准. 直接父元素没有定位, 则会继续往上找, 直到找到 body
offsetLeft: 距离左沿的距离.
offsetTop: 距离上沿的距离.
<div class="parent"> <div class="child"> div>div>
.parent { width: 500px; height: 500px; background-color: green; margin: 100px auto;}.child { width: 300px; height: 300px; background-color: red; margin-left: auto; margin-right: auto;}
var parent = document.querySelector('.parent');console.log(parent.offsetLeft, parent.offsetTop);var child = document.querySelector('.child');console.log(child.offsetLeft, child.offsetTop);
此时发现, child 的 offsetLeft 和 offsetTop 都是基于 body 来计算的. 原因就是父元素没有定位!
如果给 parent 加上 position: relative;
, 结果就是基于 parent 为基准进行计算了.
接下来, 在 son 中再嵌套一层 grandson
<div class="parent"> <div class="child"> <div class="grandchild">div> div>div>
.grandchild { width: 100px; height: 100px; background-color: purple; margin-left: auto; margin-right: auto;}
var grandchild = document.querySelector('.grandchild');console.log(grandchild.offsetLeft, grandchild.offsetTop);
此时打印的结果仍然是以 parent 为基准进行计算的.
获取大小
offsetWidth
offsetHeight
包含 padding / border 的尺寸.
<div class="box">div><style> .box { width: 300px; height: 300px; margin: 100px auto; background-color: green; padding: 10px; border: 10px solid red; }style><script> var box = document.querySelector(".box"); console.log(box.offsetWidth, box.offsetHeight);script>
很多时候元素的大小并不是通过 CSS 明确指定的(width: 100% 这种), 此时就特别需要使用 这种方式 动态获取
获取基准元素
offsetParent: 获取到当前元素的基准元素(带有定位的父节点. 如果没有父节点有定位, 则为 body)
<div class="parent"> <div class="child"> <div class="grandchild">div> div>div><script> var grandchild = document.querySelector('.grandchild'); console.log(grandchild.offsetParent);script>
注意和 parentNode 的区别.
offsetParent 是获取到带定位的父节点.
parentNode 则是获取到直接父节点. 无论是否有定位.
offset 和 style 中尺寸属性 的区别
1) offset 能获取到元素的真实尺寸, style 只能获取到行内样式.
可以看到, box 的 width 不是行内样式, 而是内嵌样式, 此时通过 style 无法获取.
2) offset 得到的结果是数字类型. style 得到的结果是字符串(带单位)
给 box 加上 内联样式 之后, 发现可以获取到结果了. style 方式得到的结果带有 px. 是个字符串.
3) offset 的结果包含了 padding / border 的值. style 不包含.
此时发现 offsetWidth 的结果包含了边框的宽度, style 则没有
4) offset 的值是只读的, 不能修改. 要想修改尺寸位置必须使用 style.
针对 offsetWidth 进行修改则没有任何作用.
注意: 如果需要获取坐标/尺寸, 就用 offset, 如果需要修改坐标/尺寸, 就用 style
代码示例: 获取鼠标在指定元素内的坐标
client 系列
动态的获取元素的尺寸, 边框大小等.
获取元素尺寸
clientWidth
clientHeight
包含 padding , 不包含 border.
也是只读属性, 不能修改.
获取边框大小
clientTop
clientLeft
获取上边框和左边框尺寸. 没有 clientRight 和 clientBottom. 想获取右边框和下边框尺寸可以通过计算获取.
offsetWidth - clientWidth - clientLeft
就得到有边框的宽度了.很少使用.
scroll 系列
scrollWidth
scrollHeight
包含 padding, 不包含 border
是内容的大小, 而不是元素框的大小.
当元素框内容空着的时候, clientHeight 和 scrollHeight 结果相同.
给 box 中加上一些内容后
我是内容....(重复很多次)
clientHeight 是元素框的尺寸.
而 scrollHeight 表示实际内容的尺寸.
scrollTop: 表示滚动条上方滚动的尺寸. (注意范围, 是从边框的下沿开始计算的)
// 给 box 的 CSS 填上 overflow: auto; 引入滚动条.
var box = document.querySelector('.box');
console.log(box.clientHeight);
console.log(box.scrollHeight);
// scroll 事件会在移动滚动条时触发.
box.addEventListener('scroll', function () {
console.log(box.scrollTop);
})
代码案例: 跟随滚动条的侧边栏
参考 B 站的侧边栏.
初始情况下, 侧边栏跟随滚动条一起滚动(绝对定位).
当滚动到一定程度后, 侧边栏不再滚动(固定定位).
为了简单, 咱们就实现一个简化版本
先实现基本的布局
<div class="container">div><div class="slidebar">div>
* { margin: 0; padding: 0; box-sizing: border-box;}body { background-color: #f3f3f3;}.container { width: 800px; height: 2000px; background-color: #fff; margin: 0 auto;}.slidebar { position: absolute; top: 300px; left: 50%; margin-left: 400px; width: 100px; height: 400px; background-color: rgb(128, 128, 0);}
然后实现滚动到一定程度后的定位切换.
假设侧边栏距离顶部 100px 时切换为固定定位.
注意: 侧边栏初始情况下距离顶部 300px. 所谓的距离 100px 意味着页面已经向上滚动了 200px 了.
var slidebar = document.querySelector('.slidebar');document.addEventListener('scroll', function () { console.log(document.documentElement.scrollTop); if (document.documentElement.scrollTop >= 200) { slidebar.style.position = 'fixed'; slidebar.style.top = '100px'; } else { slidebar.style.position = 'absolute'; slidebar.style.top = '300px'; }});
注意:
如果 html 中声明了 DTD (), 则使用
document.documentElement.scrollTop
如果 html 中未声明 DTD, 则使用
document.body.scrollTop
针对 IE9 以上浏览器, 还可以使用
window.pageYOffset
来代替.
小结
offset 主要用于获取元素位置.
client 主要用于获取元素尺寸.
scroll 主要用于获取带滚动内容的尺寸.