深入理解BFC与IFC
正常的流中就是如何把文档中的元素呈现出来 ,而布局呈现的规则就是BFC、IFC和相对位移,而BFC与IFC简单来说就是一个规则,BFC用于块级元素,IFC用于行内元素。
所谓BFC就是块级格式化上下文, Block Formatting Context,在常规流中竖着排列
IFC就是行内格式化上下文, Inline Formatting Content,在常规流中横着排列
除了常规流会影响布局外,还有浮动和绝对定位
要理解BFC与IFC,首先要理解盒子模型
1. 盒子模型
盒子分为行盒、块盒、匿名行盒、匿名块盒
结构
- content box
- padding box
- border box
- margin box
1.1 IE盒子模型
[图片上传失败...(image-5b18b9-1518507503208)]
width = content-width + padding-width + border-width
height = content-height + padding-height + border-height
1.2 标准盒子模型
[图片上传失败...(image-7d7f12-1518507503208)]
width = content-width
height = content-height
1.3 box-sizing切换IE与标准盒子模型
box-sizing 可以设置盒子模型的类型, IE8+
box-sizing:
- content-box 默认值使用标准盒子模型
- border-box 使用IE盒子模型
- inherit 继承父元素的属性
1.4 行级盒子
例子:https://codepen.io/limomo/pen/PQGdXG
css:
[图片上传失败...(image-994127-1518507503208)]
html:
[图片上传失败...(image-637e21-1518507503208)]
效果:
[图片上传失败...(image-b975d9-1518507503208)]
宽度等于其子行级盒子的外宽度
html:
[图片上传失败...(image-fe891c-1518507503208)]
效果:
[图片上传失败...(image-3ecfc-1518507503208)]
当行盒的宽度大于父宽度时会被拆分为多个行盒,一个成语形容就是五马分尸
html:
[图片上传失败...(image-625c49-1518507503208)]
效果:
[图片上传失败...(image-b53f62-1518507503208)]
行级盒子高度是由font-size决定的
宽度等于其子行级盒子的外宽度,但是当行盒的宽度大于父宽度时会被拆分为多个行盒,一个成语形容就是五马分尸。
- 行内元素的padding-top,padding-bottom和margin-top,margin-bottom是真的是无效???为啥 不懂???
- 行内元素的padding-left、padding-right、margin-left、margin-bottom属性设置是有效的
- 行内元素的padding-top、padding-bottom从显示的效果上是增加的,但其实设置的是无效的。并不会对他周围的元素产生任何影响
2. IFC
先看一个例子
html:
[图片上传失败...(image-456d21-1518507503208)]
css:
[图片上传失败...(image-fc38f4-1518507503208)]
效果:
[图片上传失败...(image-ac8c12-1518507503208)]
根据规则,span.parent所在行的line box的高度受span.parent、span.child、span.inline-block元素对应的inline-level box"高度"的影响。其中span.parent的"高度"为其line-height实际值,span.child的"高度"为其line-height实际值,而span.inline-block的"高度"为其margin box的高度。由于设置line-height:1,因此span.parent和span.child的content box高度等于line-height实际值;
根据vertical-align属性垂直对齐,造成各“高度”间并不以上边界或下边界对齐;
span.inline-block红色的上边框(border top)到span.child蓝色的下边框(border bottom)的距离再减去1px即为line box的高度。(line box的下界其实是span.child的content box的下限的,你看"其他元素"的上边框不是和span.child的下边框重叠了吗?如果那是line box的下界,那怎会出现重叠呢)
如何计算行级盒子的高度:
位于该行上的所有in-flow的inline-level box均参与该行line box高度的计算;(注意:是所有inline-level box,而不仅仅是子元素所生成的inline-level box)
各inline-level box根据vertical-align属性值相对各自的父容器作垂直方向对齐;
最上方的box的上边界到最下方的下边界则是line box的高度。
IFC的规则
盒子是水平一个接一个的排列,水平的margin,内边距,边框是可以有的。
垂直方向的对齐,可能是底部对齐,顶部对齐,也可能是基线对齐(这个是默认的);ps.这里的盒子应该是指的内联元素的盒子(span,strong等)和匿名内联盒子(只有文本,没有内联元素包含,自动创建的),他们合称内联盒子,一个或者多个内联盒子组成一个行框,行框的宽度由包含块和出现的浮动决定的(为什么有浮动呢,后面解释)
行框中的内联盒子的高度小于行框的高度时,内联盒子的垂直方向的对齐方式取决于vertical-align属性
当一个行框水平不能容纳内联盒子时,他们将会在垂直方向上产生多个行框,他们上下一个挨着一个,但是不会重叠
一般来说,行框的左边界紧挨着包含容器的左边界,行框的右边界紧挨着包含容器的右边界,(是两个边都紧挨着)。然而,浮动盒子可能存在于包含边框边界和行框边界之间(后面解释这种情况);
多个内联盒子的宽度小于包含他们的行框时,他们在水平方向的分布取决于text-align属性(默认是left)
3. BFC
A block formatting context contains everything inside of the element creating it that is not also inside a descendant element that creates a new block formatting context.
3.1 规则
- 如果给一个元素创建了一个BFC,就相当于创建了一个新的容器,容器内和容器外中的元素不会相互影响。外边的BFC规则,不会对容器里的BFC产生影响,而容器里面的BFC也不会对容器外的BFC产生影响,也就是相互隔绝,互不影响。
- 盒子的布局开始是从包含容器的顶部开始的。
- BFC内部的盒子会在内部一个接着一个在垂直方向排列
- 盒子的垂直方向的距离由margin决定,但是在同一个BFC中,在两个相邻的块级元素中,垂直margin会发生折叠
- BFC的区域不会和float重叠
- 每个盒子的左边界都要紧靠包含容器的左边界(这也就解释了为什么块级元素都是单独成一行的,如果不单独成行,第二个盒子的左边界怎么紧靠包含容器的左边界)
3.2 如何产生新的BFC
- float的值不为none。
- overflow的值不为visible。
- display的值为table-cell, table-caption, inline-block中的任何一个。
- position的值不为relative和static。
- 根元素或者其他包含它的元素
当一个元素设置了新的BFC后,就和这个元素外部的BFC没有关系了,这个元素只会去约束自己内部的子元素
4. 换行的css属性
white-space
normal: 忽略/合并空白
pre: 保留空白,如同<pre>的行为
nowrap: 忽略/合并空白,文本不会换行,直到遇到<br/>
pre-wrap: 保留空白,但是会正常地进行换行
pre-line: 忽略/合并空白,但是会正常地进行换行
inherit: 从父元素继承。
word-wrap
normal: 只在允许的断字点换行
break-word: 在长单词或URL地址内部进行换行
word-break
normal:依照亚洲和非亚洲语言的文本规则,允许在单词内换行。
keep-all:让亚洲语言文本如同非亚洲语言文本那样不允许在任意单词内换行。
break-all:允许非亚洲语言文本行如同亚洲语言文本那样可以在任意单词内换行。
对于我们而言,常用的是word-break:break-all;word-wrap:break-word;
,从而时间中英文换行的效果
5. 实际应用
5.1 清除浮动
html
[图片上传失败...(image-cf8fd7-1518507503208)]
css
[图片上传失败...(image-3abac0-1518507503208)]
效果
[图片上传失败...(image-75fbe9-1518507503208)]
通过bfc清除浮动 修改css为:
[图片上传失败...(image-aeec5c-1518507503208)]
效果
[图片上传失败...(image-9e8bc9-1518507503208)]
5.2 margin折叠问题
html
[图片上传失败...(image-23a9ee-1518507503208)]
css
[图片上传失败...(image-b91584-1518507503208)]
效果
[图片上传失败...(image-be32ec-1518507503208)]
[图片上传失败...(image-723999-1518507503208)]
修改html和css后效果:
[图片上传失败...(image-4bb262-1518507503208)]
[图片上传失败...(image-e40d6-1518507503208)]
[图片上传失败...(image-2db00e-1518507503208)]
5.3 左边固定,右边自适应布局
html:
[图片上传失败...(image-3070c7-1518507503208)]
css:
[图片上传失败...(image-7d7613-1518507503208)]
效果:
[图片上传失败...(image-71c0b5-1518507503208)]
使用bfc后效果
[图片上传失败...(image-956def-1518507503208)]
[图片上传失败...(image-39bb30-1518507503208)]
5.4 双飞翼布局
双飞翼布局也叫圣杯布局
使用较多的有flex布局还有利用BFC和负边距
flex布局:
[图片上传失败...(image-31b949-1518507503208)]
[图片上传失败...(image-6e16e9-1518507503208)]
[图片上传失败...(image-9f18a6-1518507503208)]
使用BFC和负边距:
[图片上传失败...(image-7d7071-1518507503208)]
[图片上传失败...(image-2c2d85-1518507503208)]
[图片上传失败...(image-5852df-1518507503208)]
[图片上传失败...(image-dea7e8-1518507503208)]
其中对于块元素的位移用的是绝对定位,除了这个之外,还可以使用负边距
[图片上传失败...(image-fb0477-1518507503208)]
6. 参考资料
https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Visual_formatting_model
https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context