【CSS】BFC - 块级格式化上下文
BFC(block formatting context)块级格式化上下文。
如果一个元素具有 BFC
,内部子元素无论如何都不会影响外部的元素。所以,BFC
元素是不可能发生 margin 重叠
的,因为 margin 重叠
是会影响外面的元素的; BFC
元素也可以用来清除浮动的影响,因为如果不清除,子元素浮动则父元素高度塌陷,必然会影响后面元素布局和定位,这显然有违 BFC
元素的子元素不会影响外部元素的设定。
触发BFC的情况有几下几种:
- <html>根元素;
- float 的值不为 none;
- overflow 的值为 auto、scroll 或 hidden;
- display 的值为 table-cell、table-caption 和 inline-block 中的任何一个;
- position 的值不为 relative 和 static。
BFC是一个独立的布局环境,其中的元素布局是不受外界的影响,并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。
上面几种情况下无须使用 clear:both
属性去清除浮动
BFC 与流体布局
BFC 的结界特性最重要的用途其实不是去 margin 重叠
或者是清除 float 影响
,而是实现更健壮、更智能的自适应布局。
其优点为:
- 自适应内容由于封闭而更健壮,容错性 更强。比方说,内部设置 clear:both 不会与 float 元素相互干扰而导致错位
- 自适应内容自动填满浮动以外区域,无 须关心浮动元素宽度,可以整站大规模应用
因此遇到两栏布局可以使用如下方式:
<div class="bfc"> <img class="left" src="test.jpg"> <p class="right">你好,你好,你好...</p> </div> ... .left { float: left; } .right { float: right; } .bfc { overflow: hidden; }
能实现自适应布局的属性有以下几个:
- overflow:autohidden (适用于IE7及以上)
- display:inline-block (适用于IE6、IE7)
- display:table-cell (适用于IE8)
利用以上属性可实现两套针对IE7以上的自适应布局:
1、借助overflow
.lbf-content { overflow: hidden; }
2、融合 display:table-cell 和 display:inline-block
.lbf-content { display: table-cell; width: 9999px; /* 如果不需要兼容 IE7,下面样式可以省略 */ *display: inline-block; *width: auto; }
以上两种基于BFC的自适应布局均支持无限嵌套,因此,多栏自适应可以通过嵌套方式实现。
最后,关于display:table-cell
元素内连续英文字符无法换行
的问题,可以用下面这种方式解决:
.word-break { display: table; width: 100%; table-layout: fixed; word-break: break-all; }
外边距折叠
常规流布局时,盒子都是垂直排列,两者之间的间距由各自的外边距所决定,但不是二者外边距之和。
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> </div> ...... .container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { background-color: lightgreen; margin: 10px 0; }
其渲染结果为:
理论上,两个p元素之间的外边距应当是二者外边距之和(20px)但实际上却是10px,这是外边距折叠(Collapsing Margins)
的结果。
折叠的结果按照如下规则计算:
- 1、两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
- 2、两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
- 3、两个外边距一正一负时,折叠结果是两者的相加的和。
产生折叠的必备条件:margin必须是邻接的!
利用 BFC 避免外边距折叠
BFC产生外边距折叠要满足一个条件:两个相邻元素要处于同一个BFC中。所以,若两个相邻元素在不同的BFC中,就能避免外边距折叠。
<div class="container"> <p>Sibling 1</p> <p>Sibling 2</p> <!-- 将第三个元素进行处理,创建新的BFC --> <div class="newBFC"> <p>Sibling 3</p> </div> </div> ...... .container { background-color: red; overflow: hidden; /* creates a block formatting context */ } p { margin: 10px 0; background-color: lightgreen; } .newBFC { overflow: hidden; /* creates new block formatting context */ }
结果如图所示:
由于第二个和第三个元素不属于同一个BFC,因此不会发生外边距折叠。
BFC包含浮动
浮动元素是会脱离文档流的(绝对定位元素会脱离文档流)。如果一个没有高度或者height是auto的容器的子元素是浮动元素,则该容器的高度是不会被撑开的。我们通常会利用伪元素(:after或者:before)来解决这个问题。
BFC能包含浮动,也能解决容器高度不会被撑开的问题。
<div class="container"> <div>Sibling</div> <div>Sibling</div> </div> ...... .container { background-color: green; } .container div { float: left; background-color: lightgreen; margin: 10px; }
由于父元素没有高度,内部元素浮动后脱离父元素,解决方式为将父元素变为BFC,解决方式如下:
.container { overflow: hidden; //利用overflow:hidden将父元素变为BFC background-color: green; }
多列布局使用BFC
如果我们创建一个占满整个容器宽度的多列布局,在某些浏览器中最后一列有时候会掉到下一行。这可能是因为浏览器四舍五入了列宽从而所有列的总宽度会超出容器。但如果我们在多列布局中的最后一列里创建一个新的BFC,它将总是占据其他列先占位完毕后剩下的空间。
<div class="container"> <div class="column">column 1</div> <div class="column">column 2</div> <div class="column">column 3</div> </div> ...... .column { width: 31.33%; background-color: green; float: left; margin: 0 1%; } .column:last-child { float: none; overflow: hidden; }