块级格式化上下文(BFC)

元素的布局?

在 CSS 2.1 中,有三种定位方案——普通流 (Normal Flow) 、浮动 (Floats) 和绝对定位 (Absolute Positioning) ,下面分别对这三种布局简略说明一下。

1. 普通流(Normal Flow)

在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行, 除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。

2. 浮动 (Floats)

在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。

3. 绝对定位 (Absolute Positioning)

在绝对定位布局中,元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响(如果看了上文的童鞋,会发现这点与浮动元素会影响兄弟元素是不同的),而元素具体的位置由绝对定位的坐标决定。

BFC 是什么?

BFC (Block Formatting Contexts) 即块级格式化上下文,从样式上看,它与普通的容器没有什么区别,但是从功能上,BFC 可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器没有的一些特性,例如可以包含浮动元素,上面的第二类方法(如 overflow 方法)就是触发了父元素的 BFC ,使到它可以包含浮动元素,从而防止出现高度塌陷的问题。

简单来说,BFC 就是一种属性,这种属性会影响着元素的定位以及与其兄弟元素之间的相互作用。

BFC 正是属于普通流的,因此它对兄弟元素也不会造成什么影响。

如何触发 BFC ?

  • 浮动元素:floatnone 以外的值
  • 绝对定位元素:position:absolute/fixed
  • display:inline-blocks/table-cells/table-captions
  • overflow 除了 visible 以外的值(hidden/auto/scroll
  • CSS3中 flex boxes

BFC 的特性

  1. BFC 阻止父子元素的 margin 折叠
  2. BFC 可以包含浮动的元素
  3. BFC 可以阻止元素覆盖浮动元素

不得不提IE 专有的 Layout 及 hasLayout 属性

Layout 是 IE 的专有概念,它决定了元素如何对其内容进行定位和尺寸计算,与其他元素的关系和相互作用,以及对应用还有使用者的影响。

概念说明:

  1. Layout 可以被某些 CSS property(特性)不可逆的触发,而某些 HTML 元素本身就具有 layout 。
  2. Layout 在 IE 中可以通过 hasLayout 属性来判断一个元素是否拥有 layout ,如 object.currentStyle.hasLayout
  3. Layout 是 IE 浏览器渲染引擎的一个内部组成部分。在 IE 浏览器中,一个元素要么自己对自身的内容进行组织和计算大小, 要么依赖于包含块来计算尺寸和组织内容。为了协调这两种方式的矛盾,渲染引擎采用了 hasLayout 属性,属性值可以为 true 或 false。 当一个元素的 hasLayout 属性值为 true 时,我们说这个元素有一个布局(layout),或拥有布局。

默认拥有布局的元素:

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

可触发 hasLayout 的 CSS 特性:

display:inline-block
height: (除 auto 外任何值)
width: (除 auto 外任何值)
float:left/right
position:absolute/fixed
writing-mode:tb-rl
zoom: (除 normal 外任意值)
min-height: (任意值)
min-width: (任意值)
max-height: (除 none 外任意值)
max-width: (除 none 外任意值)
overflow: (除 visible 外任意值,仅用于块级元素)
overflow-x: (除 visible 外任意值,仅用于块级元素)
overflow-y: (除 visible 外任意值,仅用于块级元素)

IE6 以前的版本(也包括 IE6 及以后所有版本的混杂模式,其实这种混杂模式在渲染方面就相当于 IE 5.5), 通过设置任何元素的 'width' 或 'height'(非 auto)都可以触发 hasLayout ; 但在 IE6 和 IE7 的标准模式中的行内元素上却不行,设置 'display:inline-block' 才可以。

hasLayout 和 block formatting context 的异同及可能产生的问题

区别

在 IE8(S) 之前的版本中,没有规范中提及的 block formatting context 和 Inline formatting context 概念,而是用 hasLayout 来达到相似的目的。

在 IE 中可通过设置 widthheightmin-widthmin-heightmax-widthmax-heightzoomwriting-mode 来触发 hasLayout,而这些特性值的设置不能够使元素创建 block formatting context。

在 IE 中很多元素默认就是拥有布局的,如 ipunt, button, select, textarea 等,但是这些元素在标准中会形成 Inline formatting context 。

共同点

两者都是决定了对内容如何定位及大小计算的规则。

两者都决定了与其他元素的相互作用的规则。

table-celltable-caption 既是 hasLayout 的元素,又是可以创建 block formatting context 的元素。

浮动元素,绝对定位元素,inline-block 元素以及除 visible 外任意值的 overflow(IE7) 在 IE 中可以触发 hasLayout,同时在标准中,又可以创建 block formatting context。

可能产生的兼容性问题:

由于 hasLayout 和 block formatting context 是对一类事物的不同理解,并且他们的启用条件不尽相同,因此如果一个元素设计时,在 IE 早期版本中触发了 hasLayout ,但在其他浏览器中又没有创建 block formatting context,或者相反,一个元素在 IE 早期版本中没有触发 hasLayout ,在其他浏览器中却创建了 block formatting context(如设置了 overflow:hidden ),将导致页面布局的重大差异。

解决方案

仅当一个元素即在 IE 早期版本中触发了 hasLayout,又在其他浏览器中创建了 block formatting context 时,才能避免上述问题的发生。即同时启用上述两者以保证各浏览器的兼容,或者相反,两者皆不启用。

使元素即生成了 block formatting context,又触发了 hasLayout

对于触发 hasLayout 的元素,通过 CSS 设置,使它产生 block formatting context;

生成 block formatting context 但是没有触发 hasLayout 的元素,通过设置 zoom:1,使其触发 hasLayout。

使元素即没有触发 hasLayout,又没有创建 block formatting context。


参考:

  1. BFC:Block Formatting Context
  2. 常规流
  3. hasLayout

添加新评论