BFC与IFC概念理解+布局规则+形成方法+用处

一只瓦罐

想要理解BFC与IFC,首先要理解另外两个概念:BoxFC(即 formatting context)。

Box

一个页面是由很多个 Box 组成的,元素的类型和 display 属性决定了这个 Box 的类型。不同类型的 Box,会参与不同的 Formatting Context。

Block level的box会参与形成BFC,比如display值为block,list-item,table的元素。

Inline level的box会参与形成IFC,比如display值为inline,inline-table,inline-block的元素。

参考:W3C文档block-level

FC(Formatting Context)

它是W3C CSS2.1规范中的一个概念,定义的是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用

常见的Formatting Context 有:Block Formatting Context(BFC | 块级格式化上下文) 和 Inline Formatting Context(IFC |行内格式化上下文)。

下面就来介绍IFC和BFC的布局规则。

IFC布局规则:

在行内格式化上下文中,框(boxes)一个接一个地水平排列,起点是包含块的顶部。水平方向上的 marginborderpadding在框之间得到保留。框在垂直方向上可以以不同的方式对齐:它们的顶部或底部对齐,或根据其中文字的基线对齐。包含那些框的长方形区域,会形成一行,叫做行框。

BFC布局规则:

W3C原文:

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.

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).

整理为中文:

  1. 内部的Box会在垂直方向,一个接一个地放置。

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

  3. 每个元素的左外边缘(margin-left), 与包含块的左边(contain box left)相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。除非这个元素自己形成了一个新的BFC。

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

  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

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

参考:
W3C文档inline-formatting
W3C文档block-formatting

怎样形成一个BFC?

块级格式化上下文由以下之一创建:

  1. 根元素或其它包含它的元素

  2. 浮动 (元素的 float 不是 none)

  3. 绝对定位的元素 (元素具有 positionabsolutefixed)

  4. 非块级元素具有 display: inline-block,table-cell, table-caption, flex, inline-flex

  5. 块级元素具有overflow ,且值不是 visible

整理到这儿,对于上面第4条产生了一个small small的疑问:为什么display: inline-block;的元素是inline level 的元素,参与形成IFC,却能创建BFC?

后来觉得答案是这样的:inline-block的元素的内部是一个BFC,但是它本身可以和其它inline元素一起形成IFC。

BFC用处

1. 清除浮动

<div class="wrap">
<section>1</section>
<section>2</section>
</div>
.wrap {
  border: 2px solid yellow;
  width: 250px;
}
section {
  background-color: pink;
  float: left;
  width: 100px;
  height: 100px;
}

可以看到,由于子元素都是浮动的,受浮动影响,边框为黄色的父元素的高度塌陷了。

BFC1

解决方案:为 .wrap 加上 overflow: hidden;使其形成BFC,根据BFC规则第六条,计算高度时就会计算float的元素的高度,达到清除浮动影响的效果。

BFC2

2. 布局:自适应两栏布局

<div>
<aside></aside>
<main>我是好多好多文字会换行的那种蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤</main>
</div>
div {width: 200px;}
aside {
  background-color: yellow;
  float: left;
  width: 100px;
  height: 50px;
}
main {
  background-color: pink;
}

可以看到右侧元素的一部分跑到了左侧元素下方。

BFC3

解决方案:为main设置 overflow: hidden; 触发main元素的BFC,根据规则第4、5条,BFC的区域是独立的,不会与页面其他元素相互影响,且不会与float元素重叠,因此就可以形成两列自适应布局

BFC4

3. 防止垂直margin合并

<section class="top">1</section>
<section class="bottom">2</section>
section {
  background-color: pink;
  margin-bottom: 100px;
  width: 100px;
  height: 100px;
}
.bottom {
  margin-top: 100px;
}

BFC5

可以看到,明明.top.bottom中间加起来有200px的margin值,但是我们只能看到100px。这是因为他们的外边距相遇发生了合并。

怎样解决:为其中一个元素的外面包裹一层元素。并为这个外层元素设置 overflow: hidden;,使其形成BFC。因为BFC内部是一个独立的容器,所以不会与外部相互影响,可以防止margin合并。

BFC6

<section class="top">1</section>
<div class="wrap">
<section class="bottom">2</section>
</div>
.wrap {
  overflow: hidden;
}
阅读 14.5k

一只瓦罐
Summarize & Share
937 声望
32 粉丝
0 条评论
你知道吗?

937 声望
32 粉丝
宣传栏