offset
offsetParent
offsetParent就是查找距离该子元素最近的进行过定位的父元素(position:absolute、relative、fixed),如果其父元素中均不存在定位则offsetParent为:body元素。
我们可以对自身的定位以及父级定位分为以下几种情况:
- 自己存在fixed定位,则其
offsetParent为null; - 自己不存在定位,且父元素也不存在定位,
offsetParent为元素 - 元素自身无定位,且父元素存在定位,
offsetParent为离自身最近且经过定位的父元素 - 元素的`offsetParent`是null
我们来看一下例子:
1、自己存在fixed定位:
<body>
<div id="box" style="position: fixed;"></div>
<script>
let box = document.querySelector('#box');
console.log(box.offsetParent); // null
</script>
</body>
2、自己不存在定位,且父元素也不存在定位:
<body>
<div id="parent">
<div id="box" ></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.offsetParent); // <body>...</body>
</script>
</body>
3、元素自身无定位,且父元素存在定位:
<body>
<div id="parent" style="position: absolute;">
<div id="box" ></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.offsetParent); // <div id="parent" style="position: absolute;">...</div>
</script>
</body>
4、元素的offsetParent:
<body>
<script>
console.log(document.body.offsetParent); // null
</script>
</body>
offsetWidth与offsetHeight
offsetWidth = box.content.width + box.border-left.width + box.border-right.width + box.padding-left.width + box.padding-right.width;
offsetHeight = box.content.height+ box.border-top.width + box.border-bottom.width + box.padding-top.width + box.padding-bottom.width;
这是基于标准盒模型的,如果是怪异盒模型呢(IE盒模型)?
<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>
#box {
box-sizing: border-box;
width: 300px;
height: 300px;
border: 1px solid red;
color: #fff;
padding: 20px;
}
</style>
</head>
<body>
<div id="parent" >
<div id="box" ></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.offsetWidth); //300
</script>
</body>
我们发现怪异盒模型的offsetWidth和offsetHeight就等于其width和height。
注意:offsetWidth和offsetHeight是只读的,不能修改,如果要修改其宽高,需要使用box.style.width = xxxx+‘px’
offsetTop与offsetLeft
offsetTop:当前元素的上边框距离他的offsetParent的上边框之间的距离(注意:这不会加上offsetParent的border)
offsetLeft:当前元素的左边框距离和他的offsetParent的左边框之间的距离(注意:这不会加上offsetparent的border)
<style>
* {
padding: 0;
margin: 0;
}
#parent {
margin: 20px;
width: 500px;
height: 500px;
background-color: red;
border: 5px solid #000;
position:relative;
}
#box {
box-sizing: border-box;
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
margin-top: 30px;
margin-left: 50px;
}
</style>
</head>
<body>
<div id="parent" >
<div id="box"></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.offsetTop); // 30
console.log(box.offsetLeft); // 50
</script>
</body>
这里的offsetTop和offsetLeft就等于其margin-top和margin-left。
如果我们当前元素有绝对定位的话:
<style>
* {
padding: 0;
margin: 0;
}
#parent {
margin: 20px;
width: 500px;
height: 500px;
background-color: red;
border: 5px solid #000;
position:relative;
}
#box {
box-sizing: border-box;
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
position: absolute;
left: 50px;
top: 100px;
}
</style>
</head>
<body>
<div id="parent" >
<div id="box"></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.offsetTop); // 100
console.log(box.offsetLeft); // 50
</script>
这里的offsetTop和offsetLeft就等于其top和left。
如果父元素没定位:
如果上面的例子father盒子没有定位,那么box盒子的offsetParent就是body,这就可以看出其实offsetTop和offsetLeft没有加上当前元素父元素的border。
<style>
* {
padding: 0;
margin: 0;
}
#parent {
margin: 20px;
width: 500px;
height: 500px;
background-color: red;
border: 5px solid #000;
}
#box {
/* box-sizing: border-box; */
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
margin: 50px;
}
</style>
</head>
<body>
<div id="parent" >
<div id="box"></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.offsetParent)
console.log(box.offsetTop); // 75
console.log(box.offsetLeft); // 75
</script>
</body>
我们可以看出,box的margin为50px,parent盒子的margin为20px,剩下的5px就是parent的border。
client
client 客户端大小
client有四个属性:
- clientWidth:content + padding;
- clientHeight:content + padding
- clientTop:上边框大小
- clientLeft:左边框大小
这些属性都是只可读的。
clientWidth与clientHeight
clientWidth === 内容区域宽度 + padding左右;
clientHeight === 内容区高度 + padding上下;
<style>
* {
padding: 0;
margin: 0;
}
#parent {
box-sizing: border-box;
margin: 20px;
width: 500px;
height: 500px;
background-color: red;
border: 5px solid #000;
}
#box {
/* box-sizing: border-box; */
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
margin: 50px;
}
</style>
</head>
<body>
<div id="parent" >
<div id="box"></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.clientWidth); // 340
console.log(box.clientHeight) // 340
</script>
</body>
如果是offsetWidth与offsetHeight就是345了。
clientTop与ClientLeft
代表边框的大小,而不是与谁的距离。
<style>
* {
padding: 0;
margin: 0;
}
#parent {
box-sizing: border-box;
margin: 20px;
width: 500px;
height: 500px;
background-color: red;
border: 5px solid #000;
}
#box {
/* box-sizing: border-box; */
width: 300px;
height: 300px;
border-top: 5px solid green;
padding: 20px;
background-color: #fff;
margin: 50px;
}
</style>
</head>
<body>
<div id="parent" >
<div id="box"></div>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.clientTop); // 5
console.log(box.clientLeft) // 0
</script>
</body>
client的作用
一般我们常常使用clientWidh与clientHeight来查看整个客户端的大小。
console.log(document.documentElement.clientWidth);
console.log(document.documentElement.clientHeight);
但是要注意的是,clientWidth这个获取到的是不加滚动条和边框的,获取到的是可见区域的宽度。
而clientHeight获取到的是可见区域的高度,不是整个页面的高度。
scroll
scrollWidth和scrollHeight
scrollWidth和scrollHeight获取到的是真实宽度和真实高度;
- scrollWidth:真实宽度,可视区的宽度+被隐藏区域的宽度
- scrollHeight:真实高度,可视区的高度+被隐藏区域的高度
<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>
* {
padding: 0;
margin: 0;
}
#box {
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
margin: 50px;
overflow: scroll;
}
li {
list-style: none;
width: 200%;
height: 50px;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.scrollWidth); // 586
console.log(box.scrollHeight); // 540
console.log(box.clientWidth); // 323
console.log(box.clientHeight); // 323
console.log(box.offsetWidth); // 350
console.log(box.offsetWidth); // 350
</script>
</body>
我们发现clientWidth和clientHeight是不包含滚动条大小的,而offsetWidth和offsetHeight是包含滚动条大小的,scrollWidth和scrollHeight是包含滚动部分的!
我们可以计算:
clientWidth==width:300 + padding:40 - 滚动条 == clientHeight
得出滚动条宽度和高度为:17
offsetWidth == width:300 + padding:40 + border:10 == offsetHeight === 350
scrollWidth中,box的宽为300,但是滚动条为17,所以真实宽度为300-17 = 283,那么li的宽度为283*2 = 586,则scrollWidth ===586。所以当有隐藏元素的时候,scrollWidth是只包括真实的(内容)宽度,不包括滚动条、padding、边框的。
如果当前元素没有隐藏元素呢?
<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>
* {
padding: 0;
margin: 0;
}
#box {
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
margin: 50px;
overflow: scroll;
}
li {
list-style: none;
height: 50px;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
</div>
<script>
let box = document.querySelector('#box');
console.log(box.scrollWidth); // 323
console.log(box.scrollHeight); // 540
console.log(box.clientWidth); // 323
console.log(box.clientHeight); // 323
console.log(box.offsetWidth); // 350
console.log(box.offsetWidth); // 350
</script>
</body>
那么scrollWidth就等于clientWidth.
scrollTop和scrollLeft
scrollTop指的是当前元素被卷去的高度,也就是内容区顶端到可见区顶端的距离;scrollLeft值的是当前元素被卷去的宽度,也就是内容区左端到可视区左端的距离。
注意:scrollTop和scrollLeft是可写可读的,也就是可以修改这个属性值。
css盒模型
CSS盒模型本质是一个盒子,由边距、边框、填充和实际内容组成。我们知道css的盒模型分为两种:标准盒模型、怪异盒模型(IE盒模型),他们又是咋计算的呢?
- 标准盒模型:
- 标准盒模型的实际宽度 === 内容区宽度 + padding + border + margin;
- 标准盒模型的width === 内容区宽度(我们设置的width);
- 增加内边距、边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸,也就是说标准盒模型的padding和border会撑大盒子。
- 怪异盒模型:
- 怪异盒模型的实际宽度 === 我们设置的宽度(width) + marin;
- 怪异盒模型的width === 内容区宽度 + padding + border;
- 内容区宽度 === 我们设置的宽度 - padding - border;
- 设置 padding 、border 后,真正宽度或高度就会改变。
- 属性值:border-box(IE盒模型)、content-box(标准盒模型)
注意: margin不会对盒子的width和height起作用,它只是会影响盒子的实际位置。
标准盒模型:
<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>
* {
padding: 0;
margin: 0;
}
#box {
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
margin: 50px;
}
</style>
</head>
<body>
<div id="box">
111
</div>
</body>
把它设置为怪异盒模型后:
<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>
* {
padding: 0;
margin: 0;
}
#box {
box-sizing: border-box;
width: 300px;
height: 300px;
border: 5px solid green;
padding: 20px;
background-color: #fff;
margin: 50px;
}
</style>
</head>
<body>
<div id="box">
111
</div>
</body>
总结:
- client:
- clientWidth和clientHeight等于:width/height + padding;
- clientTop和clientLeft:border-top和border-left;
- offset:
- offsetWidth和offsetHeight等于:width/height + padding + border;
- offsetLeft和offsetTop:本元素的顶部或者左边距离offsetParent的顶部或者左边(不加border)的距离;
- scroll:
- scrollWidth和scrollHeight:
- 没有隐藏部分:等于clientWidth/clientHeight;
- 有隐藏部分:等于实际宽度/高度 + 隐藏宽度/高度;
- scrollTop和scrollLeft:被卷去的高度或者宽度;
- scrollWidth和scrollHeight: