IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

BFC(Block formatting contexts)初探

风影博客 2015-05-29 20:09:14 累计浏览 2,881 次
本机暂存

   前端工程师求职面试的时候,或多或少都会问到一点BFC(Block formatting contexts)相关的知识。在平时的开发中我也遇到过BFC方面的问题,但是没有好好整理过这方面的知识,所以别人问我的时候,我都不敢说自己知道这么个概念o(╯□╰)o。这两天,我仔细阅读了一些文章来填补这块知识漏洞。

什么是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 formatting context;

  • inline-level box:display属性为inline, inline-block, inline-table的元素,会生成inline-level box。并且参与inline formatting context;

  • run-in box:display属性为run-in的元素,根据上下文决定对象是内联对象还是块级对象。CSS3属性!

  •    Formatting Context

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

       BFC定义

       BFC(Block Formatting Context)块级格式化上下文,它是一个独立的渲染区域,只有Block-level box参与,它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

    BFC布局规则

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

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

  • 每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)

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

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

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

  • 哪些元素会生成BFC

  • 根元素

  • float属性不为none

  • position为absolute或fixed

  • display为inline-block, table-cell, table-caption, flex, inline-flex

  • overflow不为visible

  • BFC作用与原理

       1. 自适应两栏布局

<style>  
  body {
    width: 300px;
    position: relative;
  }
  .aside {
    width: 100px;
    height: 150px;
    float: left;
    background-color: #f66;
  }
  .main {
    height: 200px;
    background-color: #fcc;
  }
</style>

<body>  
  <div class="aside"></div>
  <div class="main"></div>
</body>  

   显示效果:

   layout of aside and main

   根据BFC布局规则第3条:

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

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

   根据BFC布局规则第四条:

BFC的区域不会与float box重叠  

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

  .main {
    height: 200px;
    background-color: #fcc;
    overflow: hidden;
  }

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

   layout of aside and main

   2. 清除内部浮动

<style>  
  .par {
    border: 5px solid #fcc;
    width: 300px;
  }
  .child {
    border: 5px solid #f66;
    width: 100px;
    height: 100px;
    float: left;
  }
</style>

<body>  
  <div class="par">
    <div class="child"></div>
    <div class="child"></div>
  </div>
</body>  

   显示效果:

   float layout

   根据BFC布局规则第六条:

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

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

  .par {
    border: 5px solid #fcc;
    width: 300px;
    overflow: hidden;
  }

   效果如下:

   float layout

   3. 防止垂直margin重叠

<style>  
  p {
    width: 200px;
    line-height: 100px;
    margin: 100px;
    font-weight: bold;
    color: #f55;
    background-color: #fcc;
    text-align: center;
  }
</style>

<body>  
  <p>heihei</p>
  <p>gagaga</p>
</body>  

   显示效果

   margin collapse

   两个p之间的距离为100px,发生了margin重叠

   根据BFC布局规则第二条:

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

margin重叠规则:

* 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值
* 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值
* 两个外边距一正一负时,折叠结果是两者的相加的和

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

<style>  
  .wrap {
    overflow: hidden;
  }
  p {
    width: 200px;
    line-height: 100px;
    margin: 100px;
    font-weight: bold;
    color: #f55;
    background-color: #fcc;
    text-align: center;
  }
</style>

<body>  
  <p>heihei</p>
  <div class="wrap"><p>gagaga</p></div>
</body>  

   显示效果:

   margin collapse

总结

   其实以上的几个例子都体现了BFC布局规则第五条:

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

   因为BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。

参考

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

  •    我对BFC的理解

  •    谈外margin collapsing(外边距叠加)

  • 同分类推荐文章

    1. translateZ() (2026-06-25 21:18:56)
    2. translateY() (2026-06-25 21:17:56)
    3. translateX() (2026-06-25 21:16:01)

    查看更多 前端 文章 →

    建议继续学习

    1. 50个活力和动感的网页设计-颜色的灵感 (累计阅读 34,443)
    2. 视觉设计前瞻实用性研究(PNVD) 第二期 (累计阅读 12,979)
    3. 各公司对前端开发的职位描述 (累计阅读 10,407)
    4. iframe大小自适应 (累计阅读 10,058)
    5. 浏览器的渲染原理简介 (累计阅读 8,377)
    6. 解决IE6从Nginx服务器下载图片不Cache的Bug (累计阅读 8,358)
    7. 程序员眼里IE浏览器是什么样的 (累计阅读 8,011)
    8. 2010网页设计趋势 (累计阅读 7,819)
    9. Web前端工程师编程能力飞升之路 (累计阅读 7,693)
    10. 颜色的代码表达式 (累计阅读 7,666)