「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
一、BFC概念(What)
BFC定义
BFC(Block Format Context),直译后就是块级格式化上下文,它是网页中一个隔离的独立渲染区域,只有块级元素参与。
- 区域里面的子元素不会影响到外面的元素
- 外面的元素也不会影响到里面的子元素。
BFC的布局规则
-
默认情况,内部的块元素会在垂直方向,一个接一个地放置。每个块元素独占一行。
-
块元素垂直方向总距离,由
margin、边框大小共同决定。 -
属于同一个BFC的两个相邻元素在垂直方向上的
margin会发生重叠/合并。但水平方向的margin不会。
-
左侧BFC渲染区域的
margin,必须与右侧BFC渲染区域的margin相衔接,水平方向不会出现重叠。 -
计算父元素BFC渲染区域的高度时,内部浮动元素的高度,都必须计算在内。
二、如何创建BFC?(How)
float的值不是noneposition的值不是static或relativedisplay的值是inline-block、table-cell、table-caption、flex/inline-flexoverflow不是visible
三、BFC可以解决哪些问题?(案例)
1. 防止高度塌陷
问题现象
父元素不写高度时,子元素浮动,不占用普通文档流的位置,父元素就会失去支撑,会发生高度塌陷。如下图所示:
解决方案(4种)
| 方案 | 优点 | 缺点 |
|---|---|---|
| 父元素添加overflow:hidden | 代码少、简单 | 不能和position定位配合使用,超出的部分会被隐藏 |
| 父元素内的结尾追加一个空子元素,并设置clear:both | - | 需要添加多余的空标签及属性 |
| 父元素设置浮动 | 代码少 | 可能产生新的浮动问题 |
| 父元素末尾伪元素设置clear:both(最优) | 1.不会影响显示隐藏 2.不用添加新元素 3.更不会产生浮动问题 | - |
2. 避免垂直方向margin合并
问题现象
垂直方向上,两个元素上下margin相遇时,两元素的间的总间距并不等于两个margin的和。而是等于最大的margin。
解决方案(2种)
| 方案 | 优点 | 缺点 | 原理 |
|---|---|---|---|
| 1.用新外层div包裹下方元素 2.新元素设置overflow:hidden | 简单 | 如果父元素中部分自由定位的子元素,要超出父元素显示,就冲突了 | 新外层元素,变成一个BFC,内部元素不能超出外部,外部元素也不能进入内部 |
| 1.同上 2.父元素设置::before{content:””; display:table}(最优) | 1.既不隐藏内容 2.不添加新元素 3.又不影响高度 | - | display:table,下方元素形成平级bfc,解决了margin合并的问题 |
3. 避免垂直方向margin溢出
问题现象
子元素设置margin-top,会超出父元素上边范围,变成父元素的margin-top。
解决方案(5种)
| 方案 | 优点 | 缺点 | 原理 |
|---|---|---|---|
| 父元素设置overflow:hidden | 简单 | 如果父元素中部分自由定位的子元素,要超出父元素显示,就冲突了 | 父元素形成BFC,就必须包裹内层子元素的margin |
| 父元素添加边框,颜色设置为透明 | - | 边框会增大父元素的实际大小,导致布局错乱 | 边框本身可以阻隔margin溢出 |
| 父元素padding-top代替第一个子元素的margin-top | - | 对父元素高度有影响 | padding本身可以阻隔margin溢出 |
| 父元素内第一个子元素之前添加一个空的 | 空table元素没有大小,不占用父元素空间 | 增加一个看不见的空元素,干扰查找元素 | table的display属性默认相当于table,所以形成BFC区域。其他元素的margin不能进入table范围内,就阻隔了margin溢出 |
| 父元素::before{ content:""; display:table; }(最优) | 1.不隐藏内容 2.不添加新元素 3.不影响高度 | - | display:table,形成BFC |
4. 自适应两栏布局
如下图,左侧定宽,右侧宽度自适的布局效果,我们可以用BFC的知识来实现!!
第一步,左边定宽左浮动,形成
BFC区域;
第二步,右边元素也形成BFC渲染区域,比如设置overflow:hidden。
<!-- html -->
<div class="left">左侧定宽,侧边栏</div>
<div class="right">右侧自适应浏览器宽度</div>
/* css */
.left{
float: left;
width: 100px;
height: 250px;
background-color: greenyellow;
}
.right{
overflow: hidden;
height: 250px;
background-color: pink;
}