【CSS】BFC专题

492 阅读4分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

一、BFC概念(What)

BFC定义

BFC(Block Format Context),直译后就是块级格式化上下文,它是网页中一个隔离的独立渲染区域,只有块级元素参与。

  • 区域里面的子元素不会影响到外面的元素
  • 外面的元素也不会影响到里面的子元素。 image.png

BFC的布局规则

  • 默认情况,内部的块元素会在垂直方向,一个接一个地放置。每个块元素独占一行。 image.png

  • 块元素垂直方向总距离,由margin、边框大小共同决定。 image.png

  • 属于同一个BFC的两个相邻元素在垂直方向上的margin会发生重叠/合并。但水平方向的margin不会。

image.png

  • 左侧BFC渲染区域的margin,必须与右侧BFC渲染区域的margin相衔接,水平方向不会出现重叠。 image.png

  • 计算父元素BFC渲染区域的高度时,内部浮动元素的高度,都必须计算在内。 image.png

二、如何创建BFC?(How)

  • float的值不是none
  • position的值不是static或relative
  • display的值是inline-block、table-cell、table-caption、flex/inline-flex
  • overflow不是visible

三、BFC可以解决哪些问题?(案例)

1. 防止高度塌陷

问题现象

父元素不写高度时,子元素浮动,不占用普通文档流的位置,父元素就会失去支撑,会发生高度塌陷。如下图所示: image.png

解决方案(4种)

方案优点缺点
父元素添加overflow:hidden代码少、简单不能和position定位配合使用,超出的部分会被隐藏
父元素内的结尾追加一个空子元素,并设置clear:both-需要添加多余的空标签及属性
父元素设置浮动代码少可能产生新的浮动问题
父元素末尾伪元素设置clear:both(最优)1.不会影响显示隐藏
2.不用添加新元素
3.更不会产生浮动问题
-

2. 避免垂直方向margin合并

问题现象

垂直方向上,两个元素上下margin相遇时,两元素的间的总间距并不等于两个margin的和。而是等于最大的marginimage.png

解决方案(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-topimage.png

解决方案(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的知识来实现!! image.png 第一步,左边定宽左浮动,形成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;
}