导航
offsetParent
—— 返回一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的 table
, td
, th
, body
元素。offsetLeft/offsetTop
—— 是相对于 offsetParent
的左上角边缘的坐标。offsetWidth/offsetHeight
—— 元素的“外部” width/height,边框(border)尺寸计算在内。clientLeft/clientTop
—— 从元素左上角外角到左上角内角的距离。对于从左到右显示内容的操作系统来说,它们始终是左侧/顶部 border 的宽度。而对于从右到左显示内容的操作系统来说,垂直滚动条在左边,所以 clientLeft
也包括滚动条的宽度。clientWidth/clientHeight
—— 内容的 width/height,包括 padding,但不包括滚动条(scrollbar)。scrollWidth/scrollHeight
—— 内容的 width/height,就像 clientWidth/clientHeight
一样,但还包括元素的滚动出的不可见的部分。scrollLeft/scrollTop
—— 从元素的左上角开始,滚动出元素的上半部分的 width/height。window.pageXOffset/window.pageYOffset
document.body.scrollLeft/scrollTop
document.documentElement.scrollLeft/scrollTop
window.scrollX/scrollY
function getScrollOffset() {
if (window.pageXOffset) {
return {
left: window.pageXOffset,
top: window.pageYOffset
}
} else {
return {
left: document.body.scrollLeft + document.documentElement.scrollLeft,
top: document.body.scrollTop + document.documentElement.scrollTop
}
}
}
<!DOCTYPE html> // 标准模式
document.compatMode // 标准模式 -> "CSS1Compat"
// 怪异模式 -> "BackCompat"
window.innerWidth
window.innerHeight
document.documentElement.clientWidth / clientHeight
document.body.clientWidth / clientHeight
function getViewportSize() {
if (window.innerWidth) {
return {
width: window.innerWidth,
height: window.innerHeight
}
} else {
if (document.compat === 'BackCompat') {
return {
width: document.body.clientWidth,
height: document.body.clientHeight
}
} else {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
}
}
document.body.scrollWidth / scrollHeight
document.documentElement.scrollWidth / scrollHeight
相当于:
window.innerWidth + window.pageXOffset(滚动条拉满的情况)
function getScrollSize() {
if (document.body.scrollWidth) {
return {
width: document.body.scrollWidth,
height: document.body.scrollHeight
}
} else {
return {
width: document.documentElement.scrollWidth,
height: document.documentElement.scrollHeight
}
}
}
width/height + padding + border-width
的总和。如果 box-sizing: border-box
,元素的的尺寸等于 width/height
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
margin: 0;
padding: 0;
}
.box {
position: absolute;
left: 0;
right: 0;
width: 200px;
height: 200px;
background-color: pink;
margin: 10px;
padding: 10px;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.getElementsByClassName('box')[0];
var info = box.getBoundingClientRect(); // 不实时
console.log(info);
box.style.width = '500px';
</script>
</body>
</html>
HTMLElement.offsetLeft 是一个只读属性,返回当前元素左上角相对 HTMLElement.offsetParent 节点的左边界偏移的像素值。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
margin: 0;
padding: 0;
}
.parent {
position: relative;
top: 100px;
left: 100px;
width: 300px;
height: 300px;
background-color: pink;
}
.son {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: purple;
}
</style>
</head>
<body>
<div class="parent">
<div class="son"></div>
</div>
<script>
var parent = document.getElementsByClassName("parent")[0];
var son = document.getElementsByClassName("son")[0];
console.log({
parent: {
offsetLeft: parent.offsetLeft,
offsetTop: parent.offsetTop
}
});
console.log({
son: {
offsetLeft: son.offsetLeft,
offsetTop: son.offsetTop
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
margin: 0;
padding: 0;
}
.parent {
position: relative;
top: 100px;
left: 100px;
width: 300px;
height: 300px;
background-color: pink;
}
.son {
/* position: absolute; */
/* top: 100px; */
/* left: 100px; */
width: 100px;
height: 100px;
margin: 100px;
background-color: purple;
}
</style>
</head>
<body>
<div class="parent">
<div class="son"></div>
</div>
<script>
var parent = document.getElementsByClassName("parent")[0];
var son = document.getElementsByClassName("son")[0];
console.log({
parent: {
offsetLeft: parent.offsetLeft,
offsetTop: parent.offsetTop
}
});
console.log({
son: {
offsetLeft: son.offsetLeft,
offsetTop: son.offsetTop
}
});
</script>
</body>
</html>
.parent {
position: relative;
top: 100px;
left: 100px;
width: 300px;
height: 300px;
background-color: pink;
border: 1px solid #000; // ←
}
.parent {
position: absolute; // ←
top: 100px;
left: 100px;
width: 300px;
height: 300px;
background-color: pink;
}
或者
.parent {
position: relative;
top: 100px;
left: 100px;
width: 300px;
height: 300px;
background-color: pink;
overflow: hidden; // ←
}
如果上级是定位元素,就返回相对于上级定位元素的左边界偏移像素值,如果没有就一直往上找,直到找到 body 为止
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
margin: 0;
padding: 0;
}
.parent {
width: 300px;
height: 300px;
margin: 100px;
background-color: pink;
overflow: hidden;
}
.son {
width: 100px;
height: 100px;
margin: 100px;
background-color: purple;
}
</style>
</head>
<body>
<div class="parent">
<div class="son"></div>
</div>
<script>
var parent = document.getElementsByClassName("parent")[0];
var son = document.getElementsByClassName("son")[0];
console.log({
parent: {
offsetLeft: parent.offsetLeft,
offsetTop: parent.offsetTop
}
});
console.log({
son: {
offsetLeft: son.offsetLeft,
offsetTop: son.offsetTop
}
});
</script>
</body>
</html>
父级有定位找距父级距离,没定位找可视距离位置
由于 parent 不是定位元素,所以 son 的 offsetParent 是 body:
一旦 parent 是定位元素,例如设置 position: relative
,此时 son 的 offsetParent 就是 .parent
了:
function getElemDocPostion(el) {
var parent = el.offsetParent,
offsetLeft = el.offsetLeft,
offsetTop = el.offsetTop;
while(parent) {
offsetLeft += parent.offsetLeft;
offsetTop += parent.offsetTop;
parent = parent.offsetParent;
}
return {
left: offsetLeft,
top: offsetTop
}
}
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
margin: 0;
padding: 0;
}
.grandPa {
position: absolute;
top: 100px;
left: 100px;
width: 360px;
height: 360px;
background-color:lightskyblue;
}
.parent {
position: absolute;
top: 30px;
left: 30px;
width: 300px;
height: 300px;
background-color: pink;
overflow: hidden;
}
.son {
width: 100px;
height: 100px;
margin: 100px;
background-color: purple;
}
</style>
</head>
<body>
<div class="grandPa">
<div class="parent">
<div class="son"></div>
</div>
</div>
<script>
var parent = document.getElementsByClassName("parent")[0];
var son = document.getElementsByClassName("son")[0];
function getElemDocPostion(el) {
var parent = el.offsetParent,
offsetLeft = el.offsetLeft,
offsetTop = el.offsetTop;
while(parent) {
offsetLeft += parent.offsetLeft;
offsetTop += parent.offsetTop;
parent = parent.offsetParent;
}
return {
left: offsetLeft,
top: offsetTop
}
}
console.log(getElemDocPostion(son));
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
}
.box {
width: 3000px;
height: 5000px;
border: 5px solid pink;
}
</style>
</head>
<body>
<div class="box">
asdasdasdasdasdasdasd,asdasdasdasdasdasdasd,asdasdasdasdasdasdasd,asdasdasdasdasdasdasd
</div>
<script>
setTimeout(() => {
window.scroll(800, 800);
}, 1000);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
...
<script>
setTimeout(() => {
window.scrollTo(1000, 1000);
}, 1000);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
}
.box {
width: 3000px;
height: 5000px;
border: 5px solid pink;
}
</style>
</head>
<body>
<div class="box">
asdasdasdasdasdasdasd,asdasdasdasdasdasdasd,asdasdasdasdasdasdasd,asdasdasdasdasdasdasd
</div>
<script>
setInterval(() => {
window.scrollBy(200, 200);
}, 1000);
</script>
</body>
</html>