24
写在最前:BFC看起来是个很陌生的概念但它却时时发生在我们工作中,如何清除浮动影响?如何避免margin穿透问题?如何编写两栏自适应布局?都和BFC有这密不可分的关系,下面走进切图妞的世界,分分钟搞定BFC!

一、什么是BFC?

BFC概念

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。简而言之,BFC就是一种边距重叠的解决方案。

BFC原理

  • BFC内部元素的元素在垂直方向上的边距会发生重叠
  • BFC不会与浮动元素重叠
  • BFC是独立的容器,不会影响里面的元素,里面的元素也不会影响外面元素
  • 计算BFC元素高度时,浮动元素也会参与计算

二、BFC产生条件

主流:

  • 根元素或包含根元素的元素
  • 浮动元素:float不为none(float+float具有包裹性和破坏性导致无法自适应,一般用在块状浮动布局)
  • 绝对定位元素:position不为static或者relative(absolute脱离文档流)
  • overflow 值不为 visible 的块元素(overflow可自适应,但由于溢出不可见限制了应用场景)
  • 行内块元素:display为inline-block(inline-block具有包裹性,无法自适应,IE8以下无法识别该属性)
  • 表格单元格:元素的 display为 table-cell(HTML表格单元格默认为该值,table-cell具有包裹性,无溢出特性,绝对宽度也能自适应

非主流:

  • 表格标题:元素的 display 为 table-caption,HTML表格标题默认为该值
  • 匿名表格单元格元素:元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table
  • display 值为 flow-root 的元素
  • contain 值为 layout、content或 strict 的元素
  • 弹性元素:display为 flex 或 inline-flex元素的直接子元素
  • 网格元素:display为 grid 或 inline-grid 元素的直接子元素
  • 多列容器:元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1
  • column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中

三、BFC使用场景

1、margin穿透问题1

写样式的时候常常怀疑我的margin是被浏览器吞掉了吗?
作为一个子元素想离父元素上边距有50px的距离,正常情况下是这么显示的

<section class="sec" style="overflow:hidden">
  <article class="child">height: 50px;margin-top: 50px;</article>
</section>
.sec { background: #ebf6fd; }
.child { height: 50px;background: #09d;margin-top: 50px; line-height: 50px;}

1-11
1-12

子元素的margin-top值因为穿透问题没有实现预想效果

解决方法:使父元素变为BFC,添加overflow:hidden的样式,就会实现如下效果
<section class="sec" style="overflow:hidden">
  <article class="child">height: 50px;margin-top: 50px;</article>
</section>

1-21
1-22

2、margin穿透问题2

书写列表结构的时候,margin-top为20px,margin-bottom为20px,预想中应该出现40px的效果,但是正常情况下是这样的:

<section class="margin">
  <p>切图妞切图妞切图妞切图妞切图妞切图妞切图妞</p>
  <p>切图妞切图妞切图妞切图妞切图妞切图妞切图妞</p>
</section>
.margin {background: #ebf6fd;}
.margin p { margin: 20px auto;background: #09d; line-height: 40px;}

2-1

margin-top和margin-bottom在垂直方向的边距会发生重叠现象,margin-top和margin-bottom哪个大就间隔哪个的距离。

解决方法:给子元素再创建一个父元素,使父元素是BFC
<section class="margin">
  <div style="overflow:hidden">
    <p>切图妞切图妞切图妞切图妞切图妞切图妞切图妞</p>
  </div>
  <div style="overflow:hidden">
    <p>切图妞切图妞切图妞切图妞切图妞切图妞切图妞</p>
  </div>
</section>

2-2

3、两栏自适应布局

图片与文字组合的结构,我们经常会使图片浮动起来,利用float的包裹性,让文字环绕图片,如下:

<section class="layout">
  <img src="img/bqb1.jpg" class="left" alt="" />
  <div class="right">
    傻人有傻福
  </div>
</section>
.layout {background: #ebf6fd;margin-top: 20px;}
.layout .left { float: left; width: 150px;height: 168px;}
.layout .right {background: #09d;text-align: left; }

3-1

但是当我们想把图片和文字的区块独立分来一左一右的时候呢?

解决方法:使右侧元素为BFC,添加overflow:hidden的样式
img src="img/bqb1.jpg" class="left" alt="" />
  <div class="right" style="overflow:hidden">
    傻人有傻福
  </div>
</section>

在这里插入图片描述

当我们需要图片与文字间距20px时,有两种方法:左侧margin-right或者右侧padding-left

<img src="img/bqb1.jpg" class="left" style="margin-right:20px" />

3-3

<div class="right" style="overflow:hidden;padding-left:20px">
  傻人有傻福
 </div>

3-4

4、清除浮动

父元素包含浮动元素,导致父元素塌陷,正常情况如下:

<section class="floatBorder">
  <div class="float">切图妞切图妞切图妞切图妞切图妞切图妞切图妞</div>
</section>
.floatBorder { background: #ebf6fd;border: 1px solid #FFBE00;margin-top: 20px;}
.floatBorder .float { float: left; line-height: 50px; background: #08d;}

4-1
父元素塌陷除了border外失去高度,此时需要利用BFC内子元素即使是浮动元素也会参与计算的原理

解决方法:使父元素变成BFC,添加清除浮动类
.clearfix {*zoom: 1 }
.clearfix:after {content: '';display: table; clear: both }

4-2

四、结语

具有BFC属性的元素是一个独立的容器,它不受子元素影响也不影响子元素!当margin遇到BFC,边距重叠问题得以解决;当BFC元素身边存在浮动时,它拒绝了float的包裹性独立成一个容器不与其重叠;当浮动元素在BFC元素里面时,计算高度时将内部浮动元素也进行计算,解决了父元素塌陷的问题!
上面示例代码已上传,可下载练习修改→BFC Demo

尊重原创,如需转载请注明出处!

参考资料:
张鑫旭-CSS深入理解之overflow
MDB-块格式化上下文


切图妞
1.9k 声望1.9k 粉丝