父元素如果不指定高度,那么它的高度是由子元素高度决定,也就是被内容撑开。 例如:
<html>
<head>
<style>
.box1 {
border: 10px red solid;
}
.box2 {
width: 100px;
height: 100px;
background-color: blue;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"> </div>
</div>
</body>
</html>
展示:

这时候我们给box2设置浮动(float:left),这时候它就脱离了文档流。那这时候父元素的高度就没有内容撑着了,也就是所谓的高度塌陷。
展示:

这时候我们就想到如果把父元素设置高度不就行了么。 可以是可以,但是原本我们父元素的高度是自适应子元素内容高度的,写死了也就没有适应这么一说了。所以这个方案是不推荐的。
那怎么解决呢?
这里就要引入一个块格式化上下文
)(Block Formatting Context,BFC)概念。那它有什么作用呢?
- 父元素的垂直外边距和子元素不会重叠
- 开启BFC的元素不会被浮动元素所覆盖
- 开启BFC的元素可以包含浮动的子元素
如何开启?上面的链接里面已经详细介绍了。
然后我们来依次看下效果。
- 父元素的垂直外边距和子元素不会重叠
代码:
<html>
<head>
<style>
.box1 {
background-color: #E7A1C5;
}
.box2 {
height: 100px;
background-color: #C8CDF5;
margin-top: 10px
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>
</html>
实际效果:

我们发现子元素设置了margin-top,可是实际上也作用于父元素了,它们重叠了。那上面说到BFC可以解决这个问题,那我们现在来开启下,给父元素设置overflow:hidden; 这时效果如下:

- 开启BFC的元素不会被浮动元素所覆盖
<html>
<head>
<style>
.box1 {
background-color: #E7A1C5;
width: 100px;
height: 100px;
float: left;
}
.box2 {
height: 200px;
width: 200px;
background-color: #C8CDF5;
}
</style>
</head>
<body>
<div class="box1">
</div>
<div class="box2"></div>
</body>
</html>
展示:

由于box1设置了浮动,脱离文档流,这时box2就会上移,被box1覆盖。
我们不想box2被box1覆盖,那这时只需要给box2设置overflow:hidden就可以了。
效果:

- 开启BFC的元素可以包含浮动的子元素
那这一点其实就是解决我们的高度塌陷问题。
我们再回到最上面的代码:
<html>
<head>
<style>
.box1 {
border: 10px red solid;
overflow:hidden; /*开启BFC*/
}
.box2 {
width: 100px;
height: 100px;
background-color: blue;
float: left
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"> </div>
</div>
</body>
</html>
我们这次给box1开启了BFC,这时候我们就已经解决了高度塌陷的问题了。
但是这样的解决方式有几个缺点:
- 不兼容IE6,IE6的解决方案是设置zoom:1。
- overflow这样的方式在绝对定位时可能会有副作用。
- 开启BFC解决高度塌陷问题都会有些副作用,我们采用overflow:hidden只是因为该副作用最小。
例如: 设置元素浮动也能开启BFC,如下代码:
<html>
<head>
<style>
.box1 {
border: 10px red solid;
float:left
}
.box2 {
width: 100px;
height: 100px;
background-color: blue;
float: left
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"> </div>
</div>
</body>
</html>
效果:

虽然解决了高度塌陷问题,可是和我们原来想要的效果不一致了(父元素宽度没了)。
有没有什么解决方案是没有副作用的呢? 我们来看看clear这个属性。
首先我们先来一段代码
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.box1 {
width: 100px;
height: 100px;
background-color: lightgreen;
float: left;
}
.box2 {
width: 200px;
height: 200px;
background-color: yellow;
}
.box3 {
width: 300px;
height: 300px;
background-color: lightblue;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
效果:

那clear是干嘛的呢?它的作用是清除其它元素对当前元素的影响。它有几个可选值:
- left
- right
- both
- none(默认值)
从名字就能看出它的含义了。那这时候我想上面的代码清除浮动带来的影响,这时候可以设置box2为clear:left,效果:
image.png
这里注意下both,看名字是清除两侧浮动,可是实际上是清除对它影响最大的那个浮动。
说了这么多,还是没解决高度塌陷问题。这时候我们在原来的box2下面再加个box3。
<html>
<head>
<style>
.box1 {
border: 10px red solid;
}
.box2 {
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2">
</div>
<div class="box3">a</div>
</div>
</body>
</html>
效果:

我们发现,由于box2脱离了文档流,那么这时父元素就被box3给撑开了。
联想到clear是清除浮动给当前元素带来的影响,那这时候我们给box3设置个clear:left再看下:

我们发现现在和我们要的越来越近了,现在只不过box3多了个a,我们把它去掉看看:

解决!所以我们的解决方案是在高度塌陷的父元素最后加一个空的div,clear设置为both(因为我们不知道是左浮还是右浮)。
但是,html还是会多出一个div。那么我们怎么才能不要这个div,又能解决高度塌陷呢,答案是:after,我们给box1设置
.box1:after{
content:'';
clear:both;
display: block;
}
这才是完美解决方案~
网友评论