1.什么叫BFC
box、Formatting Context的概念
box:css布局的对象和基本单位,直观来说,就是一个页面是由多个box组成的。元素的类型和display属性,决定了这个box的类型。不同类型的box,会参与不同的Formatting Context(一个决定如何渲染文档的容器),因此box内的元素会以不同的方式渲染。
block-level box:display属性为block list-item table的元素,会生成block-level box。并且参与inline formatting context;
inline-level box:display属性为inline inline-block inline-table的元素,会生成inline-level box。并且参与inline formatting context;
run-in box : css3的。
Formatting Context:w3c css2.1中的概念。渲染规则,决定子元素如何定位,以及和其他元素的关系和相互作用。最常见的有block formatiting context(简称BFC)和inline formatting context(简称IFC)。
BFC定义:
块级格式化上下文,只有block-level box参与。它规定了内部的block-level box如何布局,并且与这个区域外部毫无关系。
BFC布局规则
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠 ;
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算;
2.哪些元素会生成BFC
- 根元素 ;
- float 属性不为none;
- position为absolute或fixed;
- display为inline-block,table-cell
- overflow不为visible;
3.BFC的作用及原理
1.自适应两栏布局
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--The viewport meta tag is used to improve the presentation and behavior of the samples
on iOS devices-->
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
<title></title>
<style>
body {
width: 300px;
position: relative;
}
.aside {
width: 100px;
height: 150px;
float: left;
background: #f66;
}
.main {
height: 200px;
background: #fcc;
}
</style>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>
根据BFC布局规则第三条:
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
根据BFC布局规则第四条:
BFC的区域不会与float box重叠。
我们可以通过通过触发main生成BFC, 来实现自适应两栏布局。
.main {
overflow: hidden;
}
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>
根据BFC布局规则第六条:
计算BFC的高度时,浮动元素也参与计算
为达到清除内部浮动,我们可以触发par生成BFC,那么par在计算高度时,par内部的浮动元素child也会参与计算。
.par {
overflow: hidden;
}
3.防止垂直 margin 重叠
<style>
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
<body>
<p>Haha</p>
<p>Hehe</p>
</body>
两个p之间的距离为100px,发送了margin重叠。
根据BFC布局规则第二条:
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
我们可以在p外面包裹一层容器,并触发该容器生成一个BFC。那么两个P便不属于同一个BFC,就不会发生margin重叠了。
<style>
.wrap {
overflow: hidden;
}
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
<body>
<p>Haha</p>
<div class="wrap">
<p>Hehe</p>
</div>
</body>
特别注意:
如果将为ul使用overflow:hidden的方式,ul生成BFC不应该再发生重叠现象可是我在chrome、firefox、ie上的测试结果都有发生重叠现象。
如果为ul设置了border或padding,那元素的margin便会被包含在父元素的盒式模型内,不会与外部div重叠。《CSS权威指南》中提到块级正常流元素的高度设置为auto,而且只有块级子元素,其默认高度将是从最高块级子元素的外边框边界到最低块级子元素外边框边界之间的距离。如果块级元素右上内边距或下内边距,或者有上边框或下边框,其高度是从其最高子元素的上外边距边界到其最低子元素的下外边距边界之间的距离。
在理解bfc的原理之前先让我们理解一下什么是margin collapse(边距坍塌&边距重叠)
在CSS当中,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为折叠,并且因而所结合成的外边距称为折叠外边距。
一个DIV和它的子DIV特别重视垂直边框或填充,也就好像是,一口锅,里面放个盆,能不能扣住里面的盆,主要看锅盖了,垂直边框或填充就是这个“锅盖”。于是解决的方式至少有以下三种:
边框,当然可以设置边框为透明;
为父容器添加padding,或者至少添加padding-top;
将父容器BFC化;
margin折叠的结果:
两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
两个外边距一正一负时,折叠结果是两者的相加的和。
产生折叠的必备条件:margin必须是邻接的!
而根据w3c规范,两个margin是邻接的必须满足以下条件:
必须是处于常规文档流(非float和绝对定位)的块级盒子,并且处于同一个BFC当中。
没有线盒,没有空隙(clearance,下面会讲到),没有padding和border将他们分隔开
都属于垂直方向上相邻的外边距,可以是下面任意一种情况
元素的margin-top与其第一个常规文档流的子元素的margin-top
元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
height为auto的元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom
高度为0并且最小高度也为0,不包含常规文档流的子元素,并且自身没有建立新的BFC的元素的margin-top和margin-bottom
以上的条件意味着下列的规则:
创建了新的BFC的元素(例如浮动元素或者’overflow’值为’visible’以外的元素)与它的子元素的外边距不会折叠;
浮动元素不与任何元素的外边距产生折叠(包括其父元素和子元素);
绝对定位元素不与任何元素的外边距产生折叠;
inline-block元素不与任何元素的外边距产生折叠;
一个常规文档流元素的margin-bottom与它下一个常规文档流的兄弟元素的margin-top会产生折叠,除非它们之间存在间隙(clearance)。
一个常规文档流元素的margin-top 与其第一个常规文档流的子元素的margin-top产生折叠,条件为父元素不包含 padding 和 border ,子元素不包含 clearance。
一个 ‘height’ 为 ‘auto’ 并且 ‘min-height’ 为 ‘0’的常规文档流元素的 margin-bottom 会与其最后一个常规文档流子元素的 margin-bottom 折叠,条件为父元素不包含 padding 和 border ,子元素的 margin-bottom 不与包含 clearance 的 margin-top 折叠。
一个不包含border-top、border-bottom、padding-top、padding-bottom的常规文档流元素,并且其 ‘height’ 为 0 或 ‘auto’, ‘min-height’ 为 ‘0’,其里面也不包含行盒(line box),其自身的 margin-top 和 margin-bottom 会折叠。
其实以上的几个例子都体现了BFC布局规则第五条:
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
因为BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。
参考资料:
1.
http://www.w3cplus.com/css/understanding-bfc-and-margin-collapse.html
BFC其实没有那么神秘,BFC只是一个独立的布局环境,理解BFC对我们日常的布局设计上有着重要的帮助,并且BFC和Margin Collapse之间有着重要关联。另外文中还提到了clear float时候所产生’clearance’的计算。希望大家有所收获。
2.
http://www.zhangxinxu.com/wordpress/2015/02/css-deep-understand-flow-bfc-column-two-auto-layout/
张鑫旭的个人博客_web前端技术文章_CSS深入理解流体特性和BFC特性下多栏自适应布局
3.
http://www.cnblogs.com/dojo-lzz/p/3999013.html
我对BFC的理解 最初这篇文章打算回答寒冬大神的 第一问 ,谈谈CSS布局。本来呢我以为布局主要涉及float跟display相关属性,以及他们的包含框、静态位置等等。后来看了大神的一片 面试文章 ,嗯?这里怎么还有个BFC,这是神马东东。待我搜索一下,萨萨萨,不看不知道,越看越糊涂,这到底是个神马东东。。。经过一个周时间的查阅资料和自我思考,在此总结一下我对BFC的认识,愿与各位道友分享,欢迎拍砖! 对CSS有了解的道友们肯定都知道盒式模型这个概念,对一个元素设置CSS,首先需要知道这个元素是block还是inline类型。而BFC就是用来格式化块级盒子,同样管理inline类型的盒子还有IFC,以及 其他的FC 。那首先我们就来看一下FC的概念。 Formatting Context:指页面中的一个渲染区域,并且拥有一套渲染规则,他决定了其子元素如何定位,以及与其他元素的相互关系和作用。 BFC:块级格式化上下文,它是指一个独立的块级渲染区域,只有Block-level BOX参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。 BFC的生成 既然上文提到BFC是…
4.
http://www.jianshu.com/p/265fb9f0de97
1.什么是BFC?在解释BFC是什么之前,需要先介绍Box、FormattingContext的概念。Box:CSS布局的基本单位Box是CSS布局的对象和基本单位,直观点来说,就是一个页面是由…
http://www.jianshu.com/p/265fb9f0de97
1.什么是BFC?在解释BFC是什么之前,需要先介绍Box、FormattingContext的概念。Box:CSS布局的基本单位Box是CSS布局的对象和基本单位,直观点来说,就是一个页面是由…