回顾一下BFC
BFC是Block Formatting Context
的缩写,译为块级格式上下文
。如果你对块级框,块框,行级框,行框等概念不了解可以先去看看框模型与视觉格式化模型
- BFC其实就是块级框的布局规则,相当于CSS页面布局的地基,并非什么神奇的概念,大家习以为常的一些东西其实最终的解释是可以归于BFC的。
- 创建了BFC的元素规定了内部的块级框如何布局,并且使该框在页面上形成一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然
- 在BFC中,框会从包含块的顶部开始,一个接一个地,垂直向下地摆放
我们常说block元素很霸道,会扩展到与父元素同宽,block元素会垂直排列,其实是因为BFC的约束。
- 两个兄弟框之间的垂直距离由
margin
属性来决定。在同一个BFC中,相邻的块级框之间的垂直外边距会出现折叠。常见的外边距折叠,其实并不是bug,而是由于BFC的约束。
- 在BFC中,每个框的左外边距边要紧贴其包含块的左边(对于从左往右的格式化),否则相反。即使在有浮动的情景下也是如此,除非框创建了一个新的BFC(在这种情况下该框可能会为了避开浮动框而变窄)。
- BFC的区域不会与float box重叠
- 计算BFC的高度时,浮动元素也参与计算
大家肯定知道overflow:hidden可以清浮动,哈哈,就是因为这个啦
- 下列情况将创建一个BFC:
- 根元素
- 浮动 (元素的 float 不为 none)
- 绝对定位元素 (元素的 position 为 absolute 或 fixed)
- 行内块 inline-blocks (元素的 display: inline-block)
注意:虽然display:inline-block的元素本身被当做一个原子行级框来格式化,但其内部会被当作块框来格式化,所以它是可以创建BFC的,而它本身是参与IFC的。
- 表格单元格 (元素的 display: table-cell,HTML表格单元格默认属性)
注意:虽然display: table-cell的元素本身不能生成块级框,但是可以包含块框,所以可以创建BFC。
- 表格标题 (元素的 display: table-caption, HTML表格标题默认属性)
- overflow 的值不为 visible的元素
- 弹性盒子 flex boxes (元素的 display: flex 或 inline-flex)
正式来用BFC做些事
1.防止margin折叠
123456789101112131415
<style type="text/css"> p{ width: 200px; height: 100px; text-align: center; } p:first-child{ margin-bottom: 30px; background: #bda; } p:last-child{ margin-top: 50px; background: #fbc; }</style>
结果是这样的:
外边距折叠咯,只有50px,而不是80px,这是根据BFC的下列规则而成
两个兄弟框之间的垂直距离由
margin
属性来决定。在同一个BFC中,相邻的块级框之间的垂直外边距会出现折叠。
注意其中的关键词,在同一个BFC中,那么我们只需让他们不在同一个BFC中就可以防止折叠了。这可以有多种方案,比如说给第一个p或第2个p加float、给第一个p或第2个p外面包裹一层容器,并触发该容器生成一个BFC、按理说第一个p或第2个p加overflow:hidden应该也可以可是实际测试并不可以,我也不懂这是why。这是demo,大家可以修改注释来查看不同的方案
2.清浮动
我们来看一个非常常见的例子
1234567891011121314
<style> ul { border: 5px solid #fcc; width: 300px; } li { border: 5px solid #bda; width:100px; height: 100px; float: left; list-style: none; }</style>
结果是这样的:
父元素的高度塌陷了,根据BFC的下列规则
计算BFC的高度时,浮动元素也参与计算
为了达到清浮动的效果,我们可以触发ul创建BFC,那么ul在计算高度时,ul内部的浮动元素li也会参与计算,这也可以有几个方案,比如ul也float、ul加overflow:hidden,为ul设置position:absolute。当然实际应用中要考虑这些属性的一些其他的影响,这是demo,大家可以修改注释来查看不同的方案。
3.自适应布局的一种方式
现在我们想创建一个两列布局,其中左侧宽度不定,右侧宽度要自适应占用剩下的空间。
我们写下如下代码
12345678910111213
body{ margin: 0;}.side { width: 300px; height: 150px; float: left; background: #fcc;}.main { height: 200px; background: #bda;}
结果如图所示
可以看到是很习以为常的一个现象,main部分的左外边距紧贴包含块的左边,虽然有side部分的这个浮动元素存在。这是因为的如下规则:
在BFC中,每个框的左外边距边要紧贴其包含块的左边(对于从左往右的格式化),否则相反。即使在有浮动的情景下也是如此,除非框创建了一个新的BFC(在这种情况下该框可能会为了避开浮动框而变窄)。
再有如下规则:
BFC的区域不会与float box重叠
那么利用这个规则,我们就只需要为main创建一个新的BFC,那就可以解决与float box重叠的问题了,最简单的加一个overflow:hidden。如果此时你想用浮动来生成BFC,那么你需要考虑一下浮动本身带来的影响,比如说:它的宽度变为刚好包裹住内容。除非你设置了一个非auto的宽度。同样如果采用绝对定位等方式来生成,也要考虑这些属性本身的一些效果。而不能认为只要能创建BFC就可以拿来实现这个效果。我们采用overflow:hidden,这个相对来说影响小一些。给main加上后就成为下面这样啦
side部分的宽度可以是不定宽的,main部分将根据side部分的宽度自适应的占据剩余宽度。但是该方法不能让main部分先渲染,因为我们在HTML中将它写在了side部分的后面。当然两栏自适应布局还有其他方式实现。
demo演示