高度塌陷
产生原因 父元素在文档流中高度默认是被子元素撑开的,当子元素脱离文档流以后,将无法再撑起父元素的高度,也就会导致父元素的高度塌陷
当子元素脱离文档流,比如说position(除relative)、float操作,若这个子元素原本是撑起父元素的高度,因为现在已经脱离文档流,也就是不与起父元素在一个层级了,那么就会造成父元素高度塌陷,不仅如此,还会使父元素的兄弟元素,也就图中的蓝色框框的位置发生改变!()]
**父元素的高度一旦塌陷,所有标准流中元素的位置将会上移,导致整个页面的布局混乱。**注意:position:relative
不会引起高度塌陷,因为它的参考系是父级标签,不仅如此,就算你的利用relative将子标签移动到父标签之外,父标签的高度依旧不变!依旧是子标签的高度!
解决高度塌陷的方法
方法一:开启父元素的 BFC(Block Formatting Context)
-
BFC是元素的隐含属性,默认关闭
-
开启 BFC 后元素将会有如下特性:
- 父元素的垂直外边距不会与子元素重叠(现象这样的情况:上下行各有一个标签,上面标签设置margin-bottom为20px,下面的标签设置margin-top为30px。默认情况下,这两个盒子的border距离其实是30px,这就是元素重叠。若不重叠那就是50px了)
- 开启 BFC 的元素不会被浮动元素所覆盖
- 开启 BFC 的元素可以包含浮动子元素
- 开启 BFC 的方式(我们经常不知不觉就开启了 BFC)
- 设置元素浮动(一般不用);
- 设置元素绝对定位(一般不用);
- 设置元素类型为
inline-block
;(一般不用) - 设置
overflow
为一个非默认值。一般都是夫标签使用overflow: hidden
来开启BFC(注意这个方法只是解决了float
导致的高度塌陷,对position
导致的高度塌陷无效);
方法二
在塌陷的父标签的最后添加一个空白的div,然后对该div进行清除浮动
<div id="box1">
<div id="box2"></div>
<div style="clear:both"></div>
</div>
存在问题:使用这种方法会在页面中添加多余的结构
有时希望清除掉其他元素浮动对当前元素产生的影响,这时可以使用clear
来完成功能
clear
可以清除其他浮动元素对当前元素的影响
方法三(最常用)
使用after
伪类,向父元素后添加一个块元素,并对其清除浮动
原理方法二一样,但是不会向页面中添加多余结构。因为我们将多余的div放进伪类中。方法二中占页面的标签:
<div style="clear: both"></div>
放进伪类中:
#first2::after{
content:'';/* 不需要在多余的div内加任何内容 */
display: block;/* div是块级标签 */
clear: both;/* 清除浮动造成的高度崩塌 */
}
还有其他方法(占位留坑)
高度崩塌的第二种情况
子元素和父元素相邻的垂直外边距默认会发生重叠,子元素的外边距会传递给父元素,这也是一种高度塌陷
问题代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box1{
height: 300px;
width: 300px;
background-color: gold;
}
#box2{
height: 50px;
width: 50px;
background-color: purple;
margin-top: 50px;
}
</style>
</head>
<body style="margin: 0;">
<div id="box1">
<div id="box2"></div>
</div>
</body>
</html>
用意是希望box2盒子距离box1盒子得外边距顶部为50px。然而实际上是box1盒子向下移动了50px,box2相对于box1没有发生相对位移。发生了子元素得外边距传递给父元素得情况。
解决方法:使用空得table标签可以隔离父子元素得外边距,阻止外边距的重叠。
在box1标签中改为如下代码即可。
<body style="margin: 0;">
<div id="box1">
<table></table>
<div id="box2"></div>
</div>
</body>
缺点:增加了页面额外的标签
所以,可以用伪类来优化一下
#box1::before{
content:'';
display: table;
}
一般在开发过程中我们都是先把解决高度崩塌的代码放在一个类中,哪里需要解决这个问题,就直接在标签里加上这个类即可。既可以解决高度塌陷,又可以确保父元素和子元素的垂直外边距不会重叠。
.clearfix::before,
.clearfix::after{
content: '';
display: table;/* table也是块级标签 */
clear: both; /* 这是用来解决第一类高度崩塌问题的 */
}