关于Visual formatting model的学习
文档树中的一个元素在网页中是如何通过CSS来确定它自己的布局呢?
我们可以把页面中的元素都可以看成是一个矩形的框,那么之前的问题显然与两种因素有关,框的位置和框的大小。那么这两种因素又是如何计算的呢?
几个名词概念
- containing block
- block-level element,block-level box,block container,block box
- inline-level element
- 匿名块级(行内)元素
- Block Formatting Context(BFC),Inline Formatting Context(IFC),都是指containing box中的一种布局的方式
VFM可以理解为是一种文字排版的方式,通常一种box对应的一种排版的上下文,但是在block box中可能存在两种,BFC和IFC。
几个block**名词之间的关系
(这里谈论的元素,默认是在普通文档流中)
(1) 首先是block-level element,表象是,这些元素会独占一行,即使是不能占满,也要霸道的不把那一行让给别的元素。
这样的一些元素有,(1)display:block的(2)display:list-item的(li)(3)display:table的。
这些block-level element会创建一个叫block-level box的东西,可以给它设置宽和高,已经垂直方向上的margin。
但是不是每一个block-level box都是block-level element,比如table box和replaced element。
(2) 接着是block container,是指只包括block-level box,或者建立了inline formatting context的一种容器,而IFC只能包含inline-level element.
也就是说block container,要么只能全包含block-level box,要么只能全包含inline-level box(block container中的行内元素会被匿名块级盒子包裹,从整体上来看还是一个呈现出block的)。
它可以有以下几种,(1)block-level box(2)non-replaced inline-block(3)non-replaced table cells.
(3) 再有如果一个box既是block container又是block-level box,那么这个box被称之为block box。
这部分有点绕,可以看一下下面的示意图
BFC是什么
从表现来看,是处于BFC中的box,从container top开始,由上至下,垂直方向的一个个’落’下来;这些box上下之间的间隙由各box的margin决定,会有margin叠加;并且这些box的margin box的左边挨着container的content box的左边缘;
什么时候情况下能构建出BFC?
float,绝对定位的元素;inline-block,table-cell,table-caption的block container;overflow != visible
的block box
containing box
通常我们说一个元素的containing box,是要在它的祖先元素上查找这个box。并且这个元素的大小与它的containing box的内容框的大小有关,这个元素的位置与containing box是谁有关。
如何确定元素的位置
首先,我们应当清楚的以下3种定位的方案:
(1) 正常文档流中包括的position为relative的块级和行内元素,还有block-level box的block formatting和inline-level box的inline formatting
(2) 绝对定位
(3) float
在知乎上看到的这个解释的比较好:
如何确定元素的大小
先了解下一耳熟能详的盒模型:
关于width,height,margin,padding,再来看下面的这个图,然后再讨论有auto时是如何计算的?
(1) 对于块级元素(非替换的行内元素直接设置width,height,垂直方向上的margin是不会生效的),从水平方向来说,需要满足下面的公式:
margin-left+border-left+padding-left+width+padding-right+border-right+margin-right=CBWidth(包含块的content box的宽度)
(tips:下面讨论的场景都是没有为元素设置padding和border的情况下)
一个auto时:
设置auto的这个属性的宽度=CBWidth-另外两个不是auto的值
二个auto时:
- margin-left(margin-right)和width是auto,那么margin-left(margin-right)会被置为0,而width会尽可能的宽,直到满足上述公式。比如CBWidth=400px,margin-right=100px,那么此时margin-left=0,width=300px.
- margin-left,margin-right是auto,那么它们俩的宽度将均分CBWidth-width之后的值。也就是假设,CBWidth=400px,width=100px,那么此时margin-left=150px,margin-right=150px.这也就是为什么设置margin-left:auto,margin-right:auto之后,元素会水平居中对齐。
三个auto时:
margin-left和margin-right都会被置为0,然后width会尽可能的宽,直到等于CBWidth
(2) 对于inline box来说,只有line-height,font-size,vertical这3个属性能对其高度影响
vertical只应用于行内元素,替换元素。vertical设置为%时,是相对于这个元素自身的line-height的。