想要理解BFC与IFC,首先要理解另外两个概念:Box 和 FC(即 formatting context)。
1.Box
一个页面是由很多个 Box 组成的,元素的类型和 display 属性决定了这个 Box 的类型。不同类型的 Box,会参与不同的 Formatting Context。box分block-level,inline-level和匿名的。
匿名box:
<div>
Some text
<p>More text</p>
</div>
其中"Some text",浏览器会为其生成一个匿名box
Block level的box会参与形成BFC,比如display值为block,list-item,table的元素。
Inline level的box会参与形成IFC,比如display值为inline,inline-table,inline-block的元素。
2.FC(Formatting Context)
它是W3C CSS2.1规范中的一个概念,定义的是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
常见的Formatting Context 有:Block Formatting Context(BFC | 块级格式化上下文) 和 Inline Formatting Context(IFC |行内格式化上下文)。
3.IFC布局规则
在行内格式化上下文中,框(boxes)一个接一个地水平排列,起点是包含块的顶部。水平方向上的 margin,border 和 padding在框之间得到保留。框在垂直方向上可以以不同的方式对齐:它们的顶部或底部对齐,或根据其中文字的基线对齐。包含那些框的长方形区域,会形成一行,叫做行框。
IFC布局规则:
1.框会从包含块的顶部开始,一个接一个地水平摆放。
2.摆放这些框时,它们在水平方向的 内外边距+边框 所占用的空间都会被考虑; 在垂直方向上,这些框可能会以不同形式来对齐: 水平的margin、padding、border有效,垂直无效。不能指定宽高;
3.行框的宽度是 由包含块和存在的浮动来决定; 行框的高度 由行高来决定
4.BFC布局规则
BFC是W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。也可以说BFC就是一个作用范围。
BFC的布局规矩:
1、内部box在垂直方向,一个接一个的放置;
2、box的垂直方向由margin决定,属于同一个BFC的两个box间的margin会重叠
3、每个元素的左外边缘(margin-left), 与包含块的左边(contain box left)相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。除非这个元素自己形成了一个新的BFC。
4、BFC区域不会与float box重叠(可用于排版);
5、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
6、计算BFC的高度时,浮动元素也参与计算
哪些元素或属性会触发BFC?
1、根元素;
2、float属性不为none;
3、position为absolute或fixed;
4、display为inline-block, flex, 或者inline-flex;
5、overflow不为visible;
CSS3触发BFC方式则可以简单描述为:在元素定位非static,relative的情况下触发,float也是一种定位方式,所以会触发BFC。(或者总结为但凡一切使div脱离文档流的属性和值,都可以形成一个新的BFC,代价是浏览器会重新渲染dom结构)
5.BFC用处
1.清除浮动
<div class="wrap">
<section>1</section>
<section>2</section>
</div>
可以看到,由于子元素都是浮动的,受浮动影响,边框为黄色的父元素的高度塌陷了。
解决方案:为 .wrap 加上 overflow: hidden;使其形成BFC,根据BFC规则第六条,计算高度时就会计算float的元素的高度,达到清除浮动影响的效果。
2.布局:自适应两栏布局
<div>
<aside></aside>
<main>我是好多好多文字会换行的那种蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤</main>
</div>
div {width: 200px;}
aside {
background-color: yellow;
float: left;
width: 100px;
height: 50px;
}
main {
background-color: pink;
}
可以看到右侧元素的一部分跑到了左侧元素下方。
解决方案:为main设置 overflow: hidden; 触发main元素的BFC,根据规则第4、5条,BFC的区域是独立的,不会与页面其他元素相互影响,且不会与float元素重叠,因此就可以形成两列自适应布局
3.防止垂直margin合并
<section class="top">1</section>
<section class="bottom">2</section>
section {
background-color: pink;
margin-bottom: 100px;
width: 100px;
height: 100px;
}
.bottom {
margin-top: 100px;
}
可以看到,明明.top和.bottom中间加起来有200px的margin值,但是我们只能看到100px。这是因为他们的外边距相遇发生了合并。
怎样解决:为其中一个元素的外面包裹一层元素。并为这个外层元素设置 overflow: hidden;,使其形成BFC。因为BFC内部是一个独立的容器,所以不会与外部相互影响,可以防止margin合并。
<section class="top">1</section>
<div class="wrap">
<section class="bottom">2</section>
</div>
.wrap {
overflow: hidden;
}
参考文章:
https://segmentfault.com/a/1190000009545742#articleHeader0
https://segmentfault.com/a/1190000004246731
https://segmentfault.com/a/1190000004466536
https://juejin.im/entry/5a8e32b25188257a5911d31e
https://juejin.im/entry/5938daf7a0bb9f006b2295db
https://www.jianshu.com/p/ba09794df241