BFC 和 HasLayout

2016/03/08 bfclayout

# BFC 的定义

是 W3C CSS2.1 规范中的一个概念,它决定了元素如何对其元素进行定位,以及与其它元素的关系和相互作用。

在创建了 Block Formating Context 的元素中,其子元素会一个接一个地放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻的元素之间的垂直距离取决于 margin 特性。在 Block Formating Context 中相邻的块级元素的垂直边距会折叠(collapse)。

在 Block Formating Context 中,每一个元素左外边距与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个 Block Formating Context。

# BFC到底是什么?

当涉及到可视化布局的时候,Block Formatting Context 提供了一个环境,HTML 元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成 BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个 BFC 就是一个独立的行政单位的意思。

# 怎样才能形成BFC

  • float 的值不为 none
  • overflow 的值不为 visible
  • display 的值为 table-cell, table-caption, inline-block 中的任何一个
  • position 的值不为 relativestatic

# BFC 的作用

  1. 不和浮动元素重叠

    如果一个浮动元素后面跟着一个非浮动的元素,那么就会产生一个覆盖的现象,很多自适应的两栏布局就是这么做的。比如下图的效果,参考例子 (opens new window)

  2. 清除元素内部浮动

    只要把父元素设为BFC就可以清理子元素的浮动了,最常见的用法就是在父元素上设置overflow: hidden样式,对于 IE6 加上zoom:1就可以了(IE Haslayout)

  3. 嵌套元素 margin 边距折叠问题的解决

    按照 BFC 的定义,只有同属于一个 BFC 时,两个元素才有可能发生垂直 margin 的重叠,这个包括相邻元素,嵌套元素,只要他们之间没有阻挡(例如边框,非空内容,padding等)就会发生 margin 重叠。

    因此要解决 margin 重叠问题,只要让它们不在同一个 BFC 就行了,但是对于两个相邻元素来说,意义不大,没有必要给它们加个外壳,但是对于嵌套元素来说就很有必要了,只要把父元素设为 BFC 就可以了。这样子元素的 margin 就不会和父元素的 margin 发生重叠了。

# IE HasLayout

Layout 是一个 Internet Explorer for Windows 的私有概念,它决定了一个元素如何显示以及约束其包含的内容、如何与其他元素交互和建立联系、如何响应和传递应用程序事件、用户事件等。这种渲染特性可以通过某些 CSS 属性被不可逆转地触发。而有些 HTML 元素则默认就具有 layout。

一个元素“得到 layout”,或者说一个元素“拥有 layout” 的时候,是指它的微软专有属性 hasLayout 被设为了 true 。一个“layout 元素”可以是一个默认就拥有 layout 的元素或者是一个通过设置某些 CSS 属性得到 layout 的元素。

不同于标准属性,也不像某些浏览器的私有 CSS 属性,layout 无法通过某一个 CSS 声明直接设定 。也就是说没有“layout 属性”这么一个东西,元素要么本身自动拥有 layout,要么借助一些 CSS 声明悄悄地获得 layout。

下列元素应该是默认具有 layout 的:

  • <html>, <body>
  • <table>, <tr>, <th>, <td>
  • <img>
  • <hr>
  • <input>, <button>, <select>, <textarea>, <fieldset>, <legend>
  • <iframe>, <embed>, <object>, <applet>
  • <marquee>

下列 CSS 属性和取值将会让一个元素获得 layout:

  • position: absolute

    绝对定位元素的包含区块(containing block)就会经常在这一方面出问题。

  • float: left | right

    由于 layout 元素的特性,浮动模型会有很多怪异的表现。

  • display: inline-block

    当一个内联级别的元素需要 layout 的时候往往就要用到它,这也可能也是这个 CSS 属性的唯一效果–让某个元素拥有 layout。inline-block行为在 IE 中是可以实现的,但是非常与众不同: IE/Win: inline-block and hasLayout 。

  • width: 除 auto 外的任意值

    很多人遇到 layout 相关问题发生时,一般都会先尝试用这个来修复。

  • height: 除 auto 外的任意值

    height: 1% 就在 Holly Hack 中用到。

  • zoom: 除 normal 外的任意值

    IE专有属性。不过 zoom: 1 可以临时用做调试。

  • writing-mode: tb-rl

    MS专有属性。

IE7中引入的hasLayout成员

  • overflow: hidden | scroll | auto

    在 IE7 中,overflow 也变成了一个 layout 触发器,这个属性在之前版本 IE 中没有触发 layout 的功能。

  • position: fixed

  • min-width: 任意值

    就算设为0也可以让该元素获得 layout。

  • max-width: 除 none 之外的任意值

  • min-height: 任意值

    即使设为0也可以让该元素的 haslayout=true

  • max-height: 除 none 之外的任意值

# 参考资料

上次更新: 2023/1/2 02:25:24