一、文档流
浏览器在渲染页面时,遵照从上往下、从左往右的顺序依次排列元素,这种页面排版方式就是文档流。
当元素设置 float 后,它会脱离文档流,就像"浮"在了页面上方。
二、浮动布局
2.1 文字环绕效果
浮动元素会脱离文档流,但一定不会覆盖文字。这是浮动最重要的特性 —— 文字会自动环绕在浮动元素周围。
<style>
img{
float: left;<!-- 浮在左边 -->
}
</style>
</head>
<body>
<div class="page"> <!-- img默认是行内元素,但可以改变大小 -->
<img width="200" src="https://img95.699pic.com/photo/50070/5999.jpg_wh860.jpg" alt="示例图片">
<p>文本</p>
</div>
</body>
效果示意:
- 如图所示,文字环绕在图片周围,并且没有覆盖掉图片,即使图片已经脱离文档流
2.2 父容器高度塌陷
浮动元素脱离文档流后,父容器无法感知其高度,导致高度塌陷:
<style>
.item {
width: 200px;
height: 100px;
float: left;
}
/* 选中class为item的元素中的第一个子元素 */
.item:nth-child(1){
background-color: #db5a5a;
}
/* 选中class为item的元素中的二个子元素 */
.item:nth-child(2){
background-color: #d1c93e;
}
.item:nth-child(3){
background-color: #159a5a;
}
</style>
<ul> <!-- 高度为 0 ,子元素都浮动了 -->
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
</ul>
<h2>hello world</h2> <!-- 这个元素会跑到浮动元素右边 -->
效果示意:
- 检查发现,
ul标签高度为0,因子元素全部脱离文档流,相当于没有子元素能够“撑开”ul的高度了 - 此时,p标签也默认占据一整行,ul标签又没有高度,故p标签会在页面顶部
- 由于浮动元素不会覆盖文字 ,故文字hello word会出现在右边
补充:行内块级元素间隙问题
使用 display: inline-block 时,HTML 代码中的换行会被渲染为空白间隙:
<style>
.item {
width: 200px;
height: 100px;
display: inline-block;
}
.item:nth-child(1){
background-color: #db5a5a;
}
.item:nth-child(2){
background-color: #d1c93e;
}
.item:nth-child(3){
background-color: #159a5a;
}
</style>
<ul>
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
<!-- 换行 → 间隙 -->
</ul>
效果示意:
解决方案:父元素设置 font-size: 0
ul {
font-size: 0; /* 消除空白间隙 */
}
.item {
display: inline-block;
font-size: 16px; /* 子元素重新设置字体大小 */
}
font-size可以改变标签内文字/字符的大小,值设为0会令文字/字符消失,即换行符消失了- 由于
ul内的文字全部消失了,子容器li中的文字也会消失,此时我们需要font-size: 16px;给子元素重新设置字体大小
三、清除浮动布局负面影响的五种方法
方法一:给父容器设置固定高度(不推荐)
ul {
height: 100px; /* 写死高度,不够灵活 */
}
方法二:末尾添加空元素 + clear(不推荐)
通过clear:left;清除左浮动, clear:right;清除右浮动, clear:both;左右浮动全部清除。
<style>
.clear {
clear: both; /* 清除左右浮动的影响 */
}
</style>
<ul>
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
<div class="clear"></div> <!-- 额外的空div -->
</ul>
缺点:添加了无意义的空元素,污染 HTML 结构。
方法三:设置 after 伪元素清除(推荐)
将伪元素的content属性设为空,这样就不会出现字符影响页面。伪元素默认是行内元素,不能设置宽高,需要先display: block;转换为块级元素
ul::after { /* 在ul中设置一个after伪元素 */
content: ''; /* 必须有 content 属性 */
clear: both;
display: block;
}
方法四:被影响元素设置 clear(不推荐)
h2 {
clear: both; /* 被浮动影响的元素自己清除 */
}
缺点:治标不治本,只能解决单个元素的问题,倘若后续需要在h2前添加元素,仍然会出现问题
方法五:将父容器设置为 BFC 容器(推荐)
通过一些语句,例如overflow: auto;可以将ul设置为BFC容器
ul {
overflow: auto; /* 触发 BFC */
}
四、BFC 详解
4.1 什么是 BFC?
BFC (Block Formatting Context)块级格式化上下文,是一个独立的渲染区域,它有一套特殊的渲染规则,使得容器内部的布局不会影响外部元素。
4.2 BFC 渲染规则
- BFC容器内部的子元素也是从上往下,从左往右排列
- BFC容器是一个独立的拥有特殊渲染规则的容器,它内部的子元素不会影响外部
- BFC容器在计算高度的时候会将浮动的子元素的高度也计算在内
4.3 如何创建 BFC 容器?
| 方式 | CSS 属性 |
|---|---|
overflow | hidden / auto / scroll / overlay |
position | absolute / fixed |
float | left / right |
display | flex / grid / inline-xxxx 等 |
4.4 BFC 解决父子 margin 重叠
HTML 中父容器的 margin-top 和子元素的 margin-top 会重叠(取较大值),这是一个经典 bug:
<style>
.parent{
height: 400px;
background-color: #4fcf32;
margin-top: 100px;
}
.child{
height: 200px;
background-color: #d221ab;
margin-top: 50px;
}
</style>
<div class="parent">
<div class="child"></div>
</div>
效果示意:
子容器(紫色容器)的margin-top应该是距离父容器(绿色容器)顶部50px,我们发现他与父容器的margin-top: 100px;重叠了
解决方案:将父容器变为 BFC
.parent{
height: 400px;
background-color: #4fcf32;
margin-top: 100px;
overflow: hidden; /* 触发 BFC,阻止 margin 穿透 */
}
效果示意:
子容器成功距离父容器顶部50px