视觉格式化模型
规定页面中多个盒子的排列规则,盒子该怎么摆放、渲染成什么样子,盒模型也包含在这个规则里面。
盒模型:规定单个盒子的规则(盒子有哪些部分组成?行盒是怎么样的,快盒是怎么样的),视觉格式化模型会根据CSS盒子模型将文档中的元素转换为一个个盒子。
该模型会根据盒子的包含块(containing block)的边界来渲染盒子。通常,盒子会创建一个包含其后代元素的包含块,但是盒子并不由包含块所限制,当盒子的布局跑到的外面称为溢出(overflow)。
视觉格式化模型,大体将页面中盒子的排列分为三种方式:
常规流、浮动、定位。
包含块
表示元素尺寸计算和位置的参照物(它的位置是相对于谁摆放的,它的尺寸大小相当于谁计算的,谁就是包含块),
元素的尺寸及位置的计算:常常会受到它的包含块所影响。对于一些属性,例如:width、height、padding、margin、绝对定位元素的偏移值(position设置为absolute或fixed等),当我们赋予百分比值时,这些值的计算值,就是通过元素的包含块计算得来的。
确定包含块:
确定一个元素的包含块过程完全依赖于这个元素的position属性:
1.如果position属性为static、relative或sticky,包含块可能由它最近的祖先块元素(比如inline-block,block或list-item元素,table,td单元格)的内容区的边缘组成,也可能会建立格式化上下文(比如说 a table container, flex container, grid container, 或者是 the block container 自身)。
2.如果postion属性为absolute,包含块就是由它最近的position的值不是static(也就是值为fixed、absolute、realative或sticky的祖先元素的内容区的边缘组成)。
3.如果position为fixed,在连续媒体的情况下包含块是viewport,在分页媒体下包含块是分页区域(page area)。
4.如果 position 属性是 absolute 或 fixed,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:
- transform 或 perspective 的值不是 none(也就是position值不是static并且transform 或 perspective 的值不是 none)
- will-change 的值是 transform 或 perspective
- filter 的值不是 none 或 will-change 的值是 filter(只在 Firefox 下生效).
- contain 的值是 paint (例如: contain: paint;)
例子:
em的包含块是div
em{
border: 2px solid blanchedalmond;
margin-left: 50%;
}
div{
width:50%;
height: 50px;
background: red;
}
span{
border:2px solid greenyellow;
}
<div>
<span>
<em>2</em>
</span>
</div>
为什么em的包含块是div不是span,个人认为行内元素在不定位的情况下不能作为包含块,因为span的width和height不能设定,所以em的margin的百分数值是相对于div元素计算的不是相当于span元素计算的。
看em的margin-left:50%;是相对于div.width的50%。
案例2:
table同是td的包含块。
<div>
<table>
<tr><td>hi</td><tr>
</table>
</div>
至于为什么我也不知道,规范并没有将tr设置为包含块。
参考mdn:
https://developer.mozilla.org/zhCN/docs/Web/CSS/Visual_formatting_model
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Containing_block#%E6%A0%B9%E6%8D%AE%E5%8C%85%E5%90%AB%E5%9D%97%E8%AE%A1%E7%AE%97%E7%99%BE%E5%88%86%E5%80%BC
https://baike.baidu.com/item/%E6%96%87%E6%A1%A3%E6%B5%81/1226695?fr=aladdin