前言
是否还在因为父容器高度塌陷感到困惑?一文带你吃透浮动布局的好处与弊端,五分钟带你学会如何清除浮动。
一、文档流
了解浮动布局前,我们先来认识一下什么为文档流与三种元素显示模式。
- 浏览器在渲染页面时,遵从从上到下,从左往右,依次排列,这种页面的排版方式就是文档流
-
块级元素:默认占据父容器的一整行,可以设置宽高
-
行内块级:可以同一行排列,也可以设置宽高
-
行内元素:可以同一行排列,不可以设置宽高
二、浮动布局
2.1 浮动本质
float:left(左) / right(右)
让块级元素脱离文档流,横向并排,原本块级元素独占一行,浮动后可以实现多元素并排布局,但一定不会盖住文字。
html
<!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>
img{
float:left; /*左浮动*/
}
</style>
</head>
<body>
<div class="page">
<img width="200" src="https://ts1.tc.mm.bing.net/th/id/OIP-C.Zte3ljd4g6kqrWWyg-8fhAHaEo?w=193&h=135&c=8&rs=1&qlt=90&o=6&dpr=1.5&pid=3.1&rm=2" alt="">
</div>
<div><p>
啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦 啦啦啦啦啦啦啦啦
</p>
</div>
</body>
</html>
我们只需要给 img 添加一个 float:left 样式,就会脱离文档流,此时 div 的高度是由 p 标签撑开的,p标签已经与img 标签重叠,但并不会盖住文字。

2.2浮动副作用:高度塌陷
父盒子的高度本来由它内部子元素撑开,但我们给子元素添加 float 属性后,子元素脱离文档流,父盒子的高度也变为0,后续容器也会被影响,即
- 浮动元素导致父容器高度塌陷,进而影响后续的容器排版

三、清除浮动
使用浮动很简单,只需要添加 float 属性,但要清除浮动带来的影响,有以下五种方法
- 1.直接给父容器设置宽高 --不推荐
如果我们上帝视角知道宽高多少可以设置,但大多时候由子元素撑开,我们也不知晓具体宽高
- 2.在浮动元素的末尾加一个空容器,设置 clear:both --不推荐
clear:left/right 清除左/右浮动影响 both就全清除
如果一千行的内容有100个浮动,那要添加一百个空盒子,浪费浏览器的渲染能力
- 3.为父容器添加 after 伪元素,在伪元素上 clear:both -- 推荐
伪元素属于行内元素,我们需要强行 display:block 让它变为块级元素,content 是伪元素专属属性,没有它,伪元素不创建,清除浮动失效
content:"" 空内容
content:"文本" 伪元素显示文字
- 4.被影响元素 clear:both -- 不推荐
被影响元素 clear:both 清除浮动影响,但只针对这个元素,如果后续还有元素,依然要 clear:both 清除影响,我们更偏向解决出现问题的元素
-
- 将父容器设置为 BFC 容器 --推荐
BFC 不是专门为了清除浮动,它在实现别的目的时,刚好能把浮动负面影响抵消掉
html
<!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>
*{
margin: 0;
padding: 0;
}
.item{
width: 200px;
height: 100px;
float: left;
}
.item:nth-child(1) {
background-color: #ed4949;
}
.item:nth-child(2) {
background-color: #dfef26;
}
.item:nth-child(3) {
background-color: #5df13c;
}
ul{ /*第一种*/
height: 100px;
}
.clear{ /*第二种*/
clear:both;
}
ul::after{ /*第三种 伪元素 行内元素*/
content: ''; /*必须存在,创建伪元素*/
clear: both; /*清除浮动,撑起父容器高度*/
display: block; /*转为块级,才能用clear*/
}
h2{ /*第四种*/
clear: both;
}
</style>
</head>
<body>
<ul>
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
<div class="clear"></div> <!-- 第二种 添加空盒子 -->
</ul>
<h2> hello world </h2>
</body>
</html>
四、BFC (block formatting context) 块级格式化上下文
4.1 BUG
父子容器的 margin-top 会重叠,子盒子写了 margin-top: 50px; 子容器不会相对于父容器向下50px,而是父子整体一起向下偏移100px,两个垂直 margin 合并,取数值较大的 100px。
html
<!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>
*{
margin: 0;
padding: 0;
}
.parent{
height: 500px;
background-color: #088d0b;
margin-top: 100px;
}
.child{
height: 200px;
background-color: rgb(232, 83, 217);
margin-top: 50px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
</html>
于是官方设计了一个叫 BFC 的容器,如果能把普通容器变为BFC容器,就不会产生这种bug。
4.2 BFC的渲染规则
-
BFC容器内部的子元素,也是从上到下,从左往右排列
-
BFC容器是一个独立的拥有特殊渲染规则的容器,它内部的子元素不会影响外部
-
BFC容器在计算高度时,会将浮动的子元素高度也计算在内
浮动的子元素不会带来父容器的高度塌陷,消除浮动负面影响
html
<!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>
*{
margin: 0;
padding: 0;
}
.parent{
width: 100%;
height: 500px;
background-color: #088d0b;
margin-top: 50px;
overflow: hidden; /*子元素超出父容器的部分隐藏,同时把容器变为BFC容器*/
}
.child{
width: 100%;
height: 200px;
background-color: rgb(232, 83, 217);
margin-top: 50px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
</html>

子元素相对于父容器向下50px,父容器相对顶部下移50px
4.3 如何创建BFC容器
-
1. overflow: hidden || auto || overlay || scroll
-
2. position: absolute || fixed
-
3. float: left || right
-
4. display: flex (把父容器设置为弹性容器) || grid || inline-xxx