视觉格式化模型
在 CSS 中,**视觉格式化模型**描述了用户代理如何获取文档树,并将其处理和显示为视觉媒体。这包括诸如计算机屏幕之类的**连续媒体**和诸如书籍或浏览器打印功能打印的文档之类的**分页媒体**。大部分信息同样适用于连续媒体和分页媒体。
在视觉格式化模型中,文档树中的每个元素根据盒模型生成零个或多个盒子。这些盒子的布局受以下因素控制:
- 盒子尺寸和类型。
- 定位方案(普通流、浮动和绝对定位)。
- 文档树中元素之间的关系。
- 外部信息(例如,视口大小、图像的内在尺寸等)。
关于视觉格式化模型的大部分信息都定义在 CSS2 中,但是,各种 CSS 布局模块扩展了这些信息。在阅读规范时,您通常会发现对 CSS2 中定义的模型的引用,因此,在阅读其他布局规范时,了解该模型以及 CSS2 中用于描述该模型的术语非常有价值。
在本文档中,我们定义了该模型并介绍了一些相关的术语和概念,并链接到更具体的页面以获取更多详细信息。
视口的角色
在连续媒体中,**视口**是浏览器窗口的查看区域。当视口大小发生变化时,用户代理可以更改页面的布局——例如,如果您调整窗口大小或更改移动设备的方向。
如果视口小于文档的大小,则用户代理需要提供一种滚动到未显示的文档部分的方法。我们最常看到的是在**块维度**中滚动——在水平的从上到下的语言中垂直滚动。但是,您可能需要设计一些需要在**内联维度**中滚动的内容。
框生成
**盒子生成**是 CSS 视觉格式化模型中从文档的元素创建盒子的部分。生成的盒子类型不同,这会影响它们的视觉格式。生成的盒子的类型取决于 CSS display
属性的值。
display
属性最初在 CSS2 中定义,并在 CSS 显示模块级别 3 中进行了扩展。此外,自 CSS2 以来,围绕显示的一些术语已更新并得到澄清。
CSS 将您的源文档呈现到画布上。为此,它会生成一个中间结构,即**盒子树**,它表示渲染文档的格式化结构。盒子树中的每个盒子都表示其对应元素(或伪元素)在画布上的空间和/或时间,而盒子树中的每个文本运行都表示其对应文本节点的内容。
然后,对于每个元素,CSS 会根据该元素的display
属性值生成零个或多个盒子。
注意:盒子通常以其显示类型来指代——例如,由具有display: block
的元素生成的盒子称为“块级盒子”或简称“块”。但是请注意,块级盒子、块级容器和盒子容器都存在细微差别;有关更多详细信息,请参见下面的块级盒子部分。
主盒子
当一个元素生成一个或多个盒子时,其中一个盒子是主盒子,它包含其后代盒子和在盒子树中生成的內容,并且也是任何定位方案中涉及的盒子。
某些元素除了主盒子之外,还可以生成其他盒子,例如display: list-item
会生成多个盒子(例如,一个主块级盒子和一个子标记盒子)。并且某些值(例如none
或contents
)会导致元素及其后代根本不生成任何盒子。
匿名盒子
当没有HTML元素可用于盒子时,就会创建匿名盒子。例如,当您在父元素上声明display: flex
,并且在其内部直接有一段未包含在其他元素中的文本时,就会发生这种情况。为了修复盒子树,会在该文本段周围创建一个匿名盒子。然后它将表现为一个弹性项目,但是,由于没有元素可以作为目标,因此无法像常规盒子一样对其进行定位和样式设置。
当您在文本段与块级元素之间交错时,也会发生相同的情况。在下一个示例中,我在一个<div>
中有一段字符串;在我的字符串中间有一个包含部分文本的<p>
元素。
该字符串在盒子树中被分成三个盒子。段落元素之前的字符串部分包装在一个匿名盒子中,然后是我们生成的盒子的<p>
,然后是另一个匿名盒子。
关于这些匿名盒子需要注意的一点是,它们继承自其直接父级的样式,但您无法通过定位匿名盒子来更改其外观。在我的示例中,我使用直接子元素选择器来定位容器的子元素。这不会更改匿名盒子,因为它们本身不是“元素”。
当字符串被内联元素分割时,会创建内联匿名盒子,例如,一个包含用<em></em>
包裹的部分的句子。这将句子分成三个内联盒子——强调部分之前的匿名内联盒子、用<em>
元素包裹的部分,然后是最终的匿名内联盒子。与匿名块级盒子一样,这些匿名内联盒子无法像<em>
那样独立设置样式;它们只是继承其容器的样式。
其他格式化上下文也会创建匿名盒子。网格布局的行为与上面弹性盒子示例相同,将文本字符串转换为具有匿名盒子的网格项目。多列布局会在列周围创建匿名列盒子;这些盒子也不能设置样式或以其他方式定位。表格布局将添加匿名盒子以创建正确的表格结构——例如,如果不存在具有display: table-row
的盒子,则添加匿名表格行。
行盒子
行盒子是包裹每一行文本的盒子。如果您浮动一个项目,然后在其后跟随一个具有背景颜色的块,则可以查看行盒子与其包含块之间的区别。
在下面的示例中,浮动<div>
后面的行盒子被缩短以包裹浮动项。盒子的背景在浮动项后面运行,因为浮动项已被移出文档流。
定位方案以及内联和外联元素
在 CSS 中,盒子可以根据三种定位方案进行布局——普通流、浮动或绝对定位。
普通流
在 CSS 中,普通流包括块级盒子的块级格式化、内联盒子的内联级格式化,还包括块级和内联级盒子的相对和粘性定位。
阅读有关 CSS 中流布局的更多信息。
浮动
在浮动模型中,盒子首先根据普通流进行布局,然后从流中取出并进行定位,通常位于左侧或右侧。内容可能会沿着浮动的一侧流动。
详细了解浮动。
绝对定位
格式化上下文和 display 属性
盒子可以被描述为具有外部显示类型,即block
或inline
。此外部显示类型指的是盒子在页面上与其他元素一起如何表现。
盒子也具有内部显示类型,用于指示其子元素的行为。对于正常的块级和内联级布局或普通流,此显示类型为flow
。这意味着子元素也将是block
或inline
。
但是,内部显示类型可能是grid
或flex
之类的类型,在这种情况下,直接子元素将显示为网格或弹性项目。在这种情况下,该元素被描述为创建网格或弹性格式化上下文。在许多方面,这类似于块级格式化上下文,但是,子元素的行为表现为弹性项目或网格项目,而不是普通流中的项目。
块级和内联级盒子之间的交互在display
属性参考中进行了描述。
此外,特定显示值的参考解释了这些格式化上下文在盒子布局方面的运作方式。
- CSS 网格布局模块
- CSS 弹性盒子布局模块
- CSS 多列布局模块
- CSS 表格模块
- CSS 列表和计数器模块
独立格式化上下文
元素要么参与其包含块的格式化上下文,要么建立独立的格式化上下文。例如,网格容器为其子元素建立了一个新的网格格式化上下文。
独立格式化上下文包含浮动,并且边距不会跨格式化上下文边界折叠。因此,创建新的块级格式化上下文可以确保浮动和边距保留在盒子内部。为此,请在您希望在其上创建新的块级格式化上下文的盒子上添加display: flow-root
。
以下示例显示了display: flow-root
的效果。具有黑色背景的盒子似乎包裹在浮动项和文本周围。如果您从可编辑的 CSS 中删除display: flow-root
,则浮动项将从盒子的底部突出,因为它不再被包含。
块级盒子
在规范中,块级盒子、块级容器和块级容器在某些地方都被称为块级盒子。这些东西有点不同,只有在没有歧义的情况下才能使用术语块级盒子。
块级容器
块级容器要么仅包含参与内联格式化上下文的内联级盒子,要么仅包含参与块级格式化上下文的块级盒子。因此,我们看到了上面解释的行为,其中引入了匿名盒子以确保所有项目都可以参与块级或内联格式化上下文。只有当元素包含块级或内联级盒子时,它才是块级容器。
内联级和块级盒子
这些分别是包含在块级容器内并分别参与内联或块级布局的盒子。
块级盒子
块级盒子是一个也是块级容器的块级盒子。如 CSS display
中所述,盒子可以是块级盒子,但不能也是块级容器(例如,它可能是弹性容器或网格容器)。