视觉格式化模型
一、视觉格式化模型
1、CSS视觉格式化模型(visual formatting model)是用来处理和在视觉媒体上显示文档是使用的计算规则。该模型是CSS的基础概念之一。视觉格式化模型会根据CSS盒子模型将文档中的元素转换为一个盒子,每个盒子的布局由以下因素决定:
盒子的尺寸:精确指定、由约束条件指定或没有指定
盒子的类型:行内盒子(inline)、行内级盒子(inline-level)、原子行内级盒子(atomic inline-level)、块盒子(block)
定位方案(positioning scheme):普通流定位、浮动定位或绝对定位
文档中的其他元素:及当前盒子的子元素或兄弟元素
视口尺寸与位置
所包含的图片的尺寸
其他的某些外部因素
2、该模型会根据的包含块(containing block)的边界来渲染盒子。通常,盒子会创建一个包含其后代元素的包含块,但是盒子并不由包含块所限制,当盒子的布局跑到包含块的外面时称为溢出(overflow)。
3、本文有许多相近的术语,需仔细阅读,为方便阅读,这里整理一下:
块(block):一个抽象的概念,一个块在文档流上占据一个独立的区域,块与块之间在垂直方向上按照次序依次堆叠。
包含块(cintaining block):包含其他盒子的块称为包含块。
盒子(box):一个抽象的概念,有CSS引擎根据文档中的内容所创建,主要用于文档元素的定位。布局和格式化等用途。盒子与元素并不是一一对应的,有时多个元素会合并成一个盒子,有时一个元素会生成多个盒子(如匿名盒子)。
块级元素(block-level element):元素的display为block、list-item、table时,该元素将成为块级元素。元素是否是块级元素仅是元素本身的属性,并不直接用于格式化上下文的创建或布局。
块级盒子(block-level box):有块级元素生成。一个块级元素至少会生成一个块级盒子,但也有可能生成多个(例如列表项元素)。
块盒子(block box):如果一个块级盒子同时也是一个块容器盒子(见下),则称其为块盒子。除具名块盒子之外,还有一类块盒子是匿名的,称为匿名块盒子(anonymous block box),匿名盒子无法被CSS选择符选中。
块容器盒子(block container box 或 block containing box):块容器盒子侧重于当前盒子作为“容器”的这一角色,它不参与当前块的布局和定位,它所描述的仅仅是当前盒子与其后代之间的关系。换句话说,块容器盒子主要用于确定其子元素的定位、布局等。
注:盒子分为块盒子和块级盒子两种,但元素只有块级元素没有块元素
行内级元素(inline-level element):display为inline、inline-block、inline-table的元素称为行内级元素。与块级元素一样,元素是否是行内及元素仅是元素本身的属性,并不直接用于格式化上下文的创建或布局。
行内级盒子(inline-level box):由行内级元素生成。行内级盒子包括行内盒子和原子行内级盒子两种,区别在于该盒子是否参与行内格式化上下文的创建或布局。
行内盒子(inline box):参与行内格式化上下文创建的行内级盒子称为行内盒子。与块盒子类似,行内盒子也分为具名行内盒子和匿名行内盒子(anonymous inline box)两种。
原子行内级盒子(atomic inline-level box):不参与行内格式化上下文创建的行内级盒子。原子行内级盒子一开始叫做原子行内盒子(atomic inline box),后被修正 。原子行内级盒子的内容不会拆分成多行显示。
二、盒子的生成
盒子的生成是CSS视觉格式化模型的一部分,用于从文档元素生成盒子。盒子由不同的类型,不同类型的盒子的格式化方法也有所不同,盒子的类型取决于CSSdisplay属性。
1、块级元素与块盒子
当元素的display为block、list-item、table时,该元素将成为块级元素。一个块级元素会被格式化成一个块,默认按照垂直方向依次排列。每个块级盒子都会参与块级格式化上下文(block formatting box)的创建,而每个块级元素都会至少生成一个块级盒子,即主块级盒子,有一些元素,如列表项元素可能会生成更多的盒子,多数块级元素只生成一个主块级盒子。
主块级盒子包含由后代元素生成的盒子以及内容,同时它也参与定位方案。
![](https://developer.mozilla.org/@api/deki/files/5995/=venn_blocks.png)
一个块级盒子可能也是一个块容器盒子。块容器盒子(block container box)要么只包含其他块级盒子,要么只包含行内盒子并同时创建一个行内格式化上下文(inline formatting box)。能够注意到块级盒子与块容器盒子是不同的这一点很重要。前者描述了元素与其父元素和兄弟元素之间的行为,而后者描述了元素跟其后代之间的行为。有些块级盒子并不是块容器盒子,比如表格,而有些块容器盒子也不是块级盒子,比如非替换行内块和非替换表格单元格。
一个同时是块容器盒子的块级盒子称为块盒子(block box)。
2、匿名块盒子
在某些情况下进行视觉格式化时,需要添加一些增补性的盒子,这些盒子不能用CSS选择符选中,因此称为匿名盒子(anonymous boxes)。不能被CSS选择符选中意味着不能用样式表添加样式,也就是说,此时所有可继承的CSS属性值都为inherit,而所有不可继承的CSS属性值都为initial。
块包含盒子可能只包含行内级盒子,也可能只包含块级盒子,但通常的文档都会同时包含两者,在这种情况下,就会在相邻的行内级盒子外创建匿名块盒子。
3、行内级元素和行内盒子
如果一个元素的display属性为inline、inline-block或inline-table,则称该元素为行内级元素。显示时,它不会生成内容块,但是可以与其他行内级内容一起显示为多行。一个典型的例子是包含多种格式内容(如强调文本、图片等)的段落,就可以有行内级元素组成。行内级元素会生成行内级盒子,该盒子同时会参与行内级格式化上下文(inline formatting context)的创建。行内盒子既是行内级盒子,也是一个其内容会参与创建其容器的行内级格式化上下文的盒子,比如所有具有display:inline样式的非替换盒子。如果一个行内级盒子的内容不参与行内格式化上下文的创建,则称为原子行内级盒子。而通过替换行内级元素或display值为inline-block或inline-table的元素创建的盒子不能被拆分为多个盒子。
4、匿名行内盒子
类似于块盒子,CSS引擎有时候也会自动创建一些行内盒子。这些行内盒子无法被选择符选中,因此是匿名的,他们从父元素那里继承那些可继承的出行,其他值保持默认值initial。
一种常见的情况是CSS引擎会自动为直接包含在块盒子中的文本创建一个行内格式化上下文,在这种情况下,这下文本会被一个足够大的匿名行内盒子多包含。但是如果仅包含空格则有可能不会生成匿名行内盒子,因为空格有可能会由于white-space的设置而被移除,从而导致最终的实际内容为空。
5、行盒子
行盒子由行内格式化上下文创建,用来显示一行文本。在块盒子内部,行盒子总是从块盒子的一边延伸到另一边(即占据整个盒子的宽度)。当有浮动元素时,行盒子会从向左浮动的元素的右边缘延伸到向右浮动的元素的左边缘。
行盒子更多是以技术性目的而存在的,web开发者通常不需要关心。
6、Run-in盒子
Run-in盒子通过display:run-in来定义,它可以是块盒子,也可以是行内盒子,这取决于紧随其后的盒子类型。Run-in盒子可以用来在可能的情况下将标题嵌入文章的第一个段落中。
注:Run-in盒子已经在CSS2.1的标准中移除了,但可能会在CSS3中作为一个实验性的内容再次加入,因此最好不要将其用于正式项目中。
三、定位规则
一旦生成了盒子以后,CSS引擎就需要定位它们以完成布局。下面是定位盒子时所使用的规则:
普通流:按照次序依次定位每个盒子
浮动:将盒子从普通流中单独拎出来,将其放到外层盒子的某一边
绝对定位:按照绝对位置来定位盒子,其位置根据盒子的包含元素所建立的绝对坐标系来计算,因此绝对定位元素有可能会覆盖其他元素
1、普通流
在普通流中,盒子会依次放置。在块格式化上下文中,盒子在垂直方向依次排列,而在行内格式化上下文中,盒子则水平排列。当CSS的position属性为static或relative,并且float为none时,其布局方式为普通流。
普通流又有两种情况:静态定位和相对定位
position为static时为静态定位,此时每个盒子根据普通流所计算出的确切位置来定位。
position为relative时为相对定位,此时每个盒子还会根据top、bottom、left和right属性的值在其原本所在的位置上产生指定大小的偏移。
2、浮动
在浮动定位中,浮动盒子会浮动到当前行的开始或尾部位置。这会导致普通流中的文本及其他内容会“流”到浮动盒子的边缘处,除非元素通过clear清楚了而前面的浮动。
一个盒子的float值不为none,并且其position为static或relative时,该盒子为浮动定位。如果将float设置为left,浮动盒子会定位到当前盒子的开始位置(左侧),如果设置为right,浮动盒子会定位到当前行盒子的尾部位置(右侧)。不管是左浮动还是右浮动,行盒子都会伸缩以适应浮动盒子的大小。
3、绝对定位
在绝对定位中,盒子会完全从当前流中移除,并且不会再与其有任何联系(这里仅指定位和位置计算,而绝对定位的元素在文档树中任然与其他元素有父子或兄弟等关系),其位置会使用top、bottom、left和right相对其包含块进行计算。
如果元素的position为absolute或fixed,该元素为绝对定位。
对固定位置的元素来说,其包含块为整个视口,该元素相对视口进行绝对定位,因此滚动时元素的位置并不会改变。