本人已参与新人「创作礼活动」,一起开启掘金创作之路。
格式化上下文:元素在页面上水平或垂直排布时彼此之间有何种影响;对此,CSS有几套不同的规则。本文主要介绍 IFC、BFC
一、IFC (inline formatting content) 内联格式化上下文
IFC的line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)
1.1 IFC常见用途:
水平居中:当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,通过text-align则可以使其水平居中。
垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。
1.2 布局规则
- 排版:IFC中的元素会在一行中从左到右排列;且在每一行都会形成一个新的行框;行框的元素内遵循text-align和vertical-align
- 不可变大小:对行内盒子设置宽度、高度不起作用;行内盒子文本的垂直方向上的间距不受其垂直方向上的内边距、边框、外边距的影响; 尤其是外边距根本无任何作用,而边框、内边距在多行文本中,下面文本的会遮挡上面的文本内容; 每行文本都有上下边框、内边距,而左右边框仅存在于行内盒子的开始和结尾处
- 可变大小:行框的高度为包含框的高度,高度为行框中最高元素的高度; 垂直方向可以通过修改行高 line-height(决定一个内联元素的真实占行高度) 水平方向可通过修改内边距、边框、外边距的大小;
- 行盒子缩短:浮动的元素不会在行框中,并且浮动元素会压缩行框的宽度;
.box {
width: 450px;
height: 300px;
border: 1px solid red;
}
span {
line-height: 24px;
padding: 5px 20px;
/* 上下外边距不起任何作用 */
margin: 20px 20px;
border: 3px solid green;
background-color: pink;
font-size: 16px;
}
<div class="box">
<span>1. 行内盒子沿文本流水平排列,也会随文本换行儿换行</span>
<span>
2. 行内盒子的大小:设置宽度、高度不起作用;
可以通过修改行高 line-height(决定一个内联元素的真实占行高度)
或者水平方向的内边距、边框、外边距
</span>
<span>
3. 行内盒子文本的垂直间距不受其垂直方向上的内边距、边框、外边距的影响;
同时,外边根本无任何作用,而边框、内边距会在多行文本中,下面文本的会遮挡上面的文本内容;
每行文本都有上下边框、内边距,而左右边框仅存在于行内盒子的开始和结尾处。
</span>
</div>
二、BFC (Block Formatting Contexts) 块格式化上下文
块级格式化上下文,形成一个独立的渲染区域来规定内部如何布局,且与这个区域外部毫不相干。
2.1 触发BFC的几种方式
注意: 这几种方式,不一定在任何情况下都能得到你想要的结果!!!在某些场景下,使用下面的某个方式会起作用;在其他场景下,使用另外的方式才会起作用;不能进行粗犷的统一论断,要想彻底吃透需要下功夫进行细扣、深思和研究
1. 根元素,即HTML元素
2. float 非 none
3. position 非 relative和static
4. overflow 非 visible
5. dispaly: inline-block、block、table-cell、flex、inline-flex;
其他方式
2.2 BFC的3种用途
1. 自适应多栏布局
2. 防止高度塌陷 (即高度包住浮动元素)
3. 防止垂直方向上margin折叠 (折叠条件:只发生在常规文档流中块级盒子的垂直方向上!!!)
1)自适应多栏布局 (注意两个浮动的img要写在前,且给非浮动元素使用左右margin是从父盒子的左右边开始的;可以选择给浮动元素设置margin)
.box { width: 300px; border: 1px solid blue; }
.img1 { float: left; width: 100px; }
/* .img1 { float: left; width: 100px; margin-right: 10px; } */
.img2 { float: right; width: 100px; }
/* .img2 { float: right; width: 100px; margin-left: 10px; } */
.box2 { background-color: pink; overflow: auto; }
<div class="box">
<img class="img1" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdesk-fd.zol-img.com.cn%2Ft_s960x600c5%2Fg2%2FM00%2F00%2F0B%2FChMlWl6yKqyILFoCACn-5rom2uIAAO4DgEODxAAKf7-298.jpg" alt="">
<img class="img2" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdesk-fd.zol-img.com.cn%2Ft_s960x600c5%2Fg2%2FM00%2F00%2F0B%2FChMlWl6yKqyILFoCACn-5rom2uIAAO4DgEODxAAKf7-298.jpg" alt="">
<div class="box2">
创建自己的块级格式化上下文,形成一个独立的渲染区域来规定内部如何布局,且与这个区域外部毫不相干
</div>
</div>
2)防止高度塌陷
外边距重叠时边距计算规则:
符号参与运算
1) margin同正,则取最大值;
2) margin同负,则取最小值;
3) margin一正一负,则取二者之和。
- 普通情况对比
.box { width: 300px; border: 1px solid blue;}
.img1 { float: left; width: 100px; }
.box2 { background-color: pink;}
<div class="box">
<img class="img1" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdesk-fd.zol-img.com.cn%2Ft_s960x600c5%2Fg2%2FM00%2F00%2F0B%2FChMlWl6yKqyILFoCACn-5rom2uIAAO4DgEODxAAKf7-298.jpg" alt="">
<div class="box2">
创建自己的块级格式化上下文
</div>
</div>
.box { width: 300px; border: 1px solid blue; overflow: auto; }
3)防止垂直方向上margin折叠
-
折叠条件: 只发生在常规文档流中块级盒子的垂直方向上
-
折叠分类:
- 父子元素之间 —— 仅限给父元素设置内边距、边框、
::before伪元素(必须带height属性且值大于零)来分割外边距;overflow: hidden 触发BFC;提示:outeline不可以,只是装饰线,不占实际空间,会遮挡周围元素。 - 兄弟元素之间 —— 外层元素margin边距用padding代替;
display: inline-flex,display: inline-block,注意此时的flex | block是不起作用的 - 空元素自身 —— 增加文本(如123)、内边距、边框、
::before|after伪元素(带height属性且值大于零)来分割外边距; overflow: hidden 触发BFC - 递归折叠 —— 折叠后的外边距又碰到了其他元素的外边距,还会继续折叠
- 父子元素之间 —— 仅限给父元素设置内边距、边框、
* { padding: 0; margin: 0;}
body { background-color: palegreen;}
/* .box { width: 300px; background-color: pink; margin-top: 30px; } */
.box { width: 300px; background-color: pink; margin-top: 30px; overflow: hidden; }
.box1 { width: 100px; height: 100px; background-color: red; margin-top: 20px; }
<div class="box">
<div class="box1"></div>
</div>
.box { width: 300px; background-color: pink; }
.box1 { width: 100px; height: 100px; background-color: red; padding-bottom: 30px; background-clip: content-box; border: 1px solid goldenrod;}
.box2 { width: 100px; height: 100px; background-color: red; padding-top: 20px; background-clip: content-box; border: 1px solid goldenrod;}
<div class="box">
<div class="box1"></div>
<div class="box2"></div>
</div>
.box { width: 300px; background-color: pink; }
.box1 { width: 100px; height: 100px; background-color: red;}
/* .box2 { margin: 20px; } */
/* .box2 { margin: 20px; overflow: hidden; } */
.box2 { margin: 20px; border: 1px solid red; }
.box3 { width: 100px; height: 100px; background-color: gold; }
<div class="box">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</div>
三、TFC (Table Formatting Contexts) 表格式化上下文
四、GFC (Grid Formatting Contexts) 网格格式化上下文
GFC将改变传统的布局模式,他将让布局从一维布局变成了二维布局。简单的说,有了GFC之后,布局不再局限于单个维度了。这个时候你要实现类似九宫格,拼图之类的布局效果显得格外的容易。
五、FFC (Flex Formatting Contexts) 弹性格式化上下文
整体来说,FFC与BFC有点儿类似,但有以下几点区别:
- Flexbox 不支持 ::first-line 和 ::first-letter 这两种伪元素。
- vertical-align对Flexbox中的子元素是没有效果的。
- float 和 clear 属性对Flexbox中的子元素是没有效果的,也不会使子元素脱离文档流(但是对Flexbox 是有效果的!)。
- 多栏布局(column-*) 在 Flexbox 中也是失效的,就是说我们不能使用多栏布局在Flexbox 排列其下的子元素。
- Flexbox 下的子元素不会继承父级容器的宽度。