More than code
Welcome to the website

对BFC的理解及应用

一、什么是BFC?

在解释 BFC 是什么之前,需要先介绍 Box、Formatting Context的概念。

Box: CSS布局的基本单位

Box 是 CSS 布局的对象和基本单位, 直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此Box内的元素会以不同的方式渲染。让我们看看有哪些盒子:

  • block-level box:display 属性为 block, list-item, table 的元素,会生成 block-level box。并且参与 block fomatting context;
  • inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。并且参与 inline formatting context;
  • run-in box: css3 中才有, 这儿先不讲了。

Formatting context

Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。

CSS2.1 中只有 BFC 和 IFCCSS3 中还增加了 GFC 和 FFC。

BFC 定义

先看W3C文档:

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the‘margin’ properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

Block Formatting Context,中文直译为块级格式上下文。BFC就是一种布局方式,在这种布局方式下,盒子们自所在的containing block顶部一个接一个垂直排列,水平方向上撑满整个宽度(除非内部盒子自己建立了新的BFC)。两个相邻的BFC之间的距离由margin决定。在同一个BFC内部,两个垂直方向相邻的块级元素的margin会发生“塌陷”。

文档这里也间接指出了垂直相邻盒子margin合并的解决办法:就是给这两个盒子也创建BFC。

通俗一点,可以把BFC理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。

BFC布局规则:

  1. 内部的Box会在垂直方向,一个接一个地放置。
  2. Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  3. 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  4. BFC的区域不会与float box重叠。
  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  6. 计算BFC的高度时,浮动元素也参与计算

二、如何创建BFC

官方文档这么说:

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

总结一下就是:

  • 根元素
  • float属性不为none
  • overflow不为visible(可以是hidden、scroll、auto)
  • position为absolute或fixed
  • display为inline-block、table-cell、table-caption

三、BFC的作用

1. 清除内部浮动

<!-- html -->
<div class="par">
   <div class="child"></div>
   <div class="child"></div>
</div>
/* css */
.par {
   border: 5px solid #fcc;
   width: 300px;
}
.child {
   border: 5px solid #f66;
   width:100px;
   height: 100px;
   float: left;
}

效果如图:

根据BFC布局规则第六条:

计算BFC的高度时,浮动元素也参与计算

为达到清除内部浮动,我们可以触发par生成BFC,那么par在计算高度时,par内部的浮动元素child也会参与计算。

.par {
    overflow: hidden;
}

效果如图:

2.垂直margin合并

<!-- html -->
<p>Haha</p>
<p>Hehe</p>
/* css */
p{
    color: #f55;
    background: #fcc;
    width: 200px;
    line-height: 100px;
    text-align:center;
    margin: 100px;
}

效果如图:

两个p之间的距离为100px,发送了margin重叠。
根据BFC布局规则第二条:

Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠

我们可以在p外面包裹一层容器,并触发该容器生成一个BFC。那么两个P便不属于同一个BFC,就不会发生margin重叠了。

<!-- html -->
<body>
   <p>Haha</p>
   <div class="wrap">
      <p>Hehe</p>
   </div>
</body>
/* css */
.wrap {
   overflow: hidden;
}
p {
   color: #f55;
   background: #fcc;
   width: 200px;
   line-height: 100px;
   text-align:center;
   margin: 100px;
}

效果如图:

3.创建自适应两栏布局

<!-- html -->
<div class="aside"></div>
<div class="main"></div>
/* css */
body {
   width: 300px;
   position: relative;
}
 
.aside {
   width: 100px;
   height: 150px;
   float: left;
   background: #f66;
}
 
.main {
   height: 200px;
   background: #fcc;
}

效果如图:

根据BFC布局规则第3条:

每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

因此,虽然存在浮动的元素aslide,但main的左边依然会与包含块的左边相接触。

根据BFC布局规则第四条:

BFC的区域不会与float box重叠。

我们可以通过通过触发main生成BFC, 来实现自适应两栏布局。

.main {
    overflow: hidden;
}

当触发main生成BFC后,这个新的BFC不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄。效果如下:

四、主要参考

CSS深入理解流体特性和BFC特性下多栏自适应布局

前端精选文摘:BFC 神奇背后的原理

赞(0) 打赏
未经允许不得转载:李帅帅空间 » 对BFC的理解及应用

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏