Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(css): Move CSS examples and sync translation - Visual formatting model #25096

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 112 additions & 42 deletions files/zh-cn/web/css/visual_formatting_model/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,75 +5,105 @@ slug: Web/CSS/Visual_formatting_model

{{CSSRef}}

CSS **视觉格式化模型**(visual formatting model)是用来处理和在视觉媒体上显示文档时使用的计算规则。该模型是 CSS 的基础概念之一
CSS 中,**视觉格式化模型**(visual formatting model)描述了用户代理如何获取文档树,并将其处理后显示在视觉媒体上。这包括{{glossary("continuous media", "连续媒体")}}(例如电脑屏幕,以及书籍或浏览器打印功能打印的文档等[分页媒体](/zh-CN/docs/Web/CSS/CSS_paged_media))。大部分信息同样适用于连续媒体和分页媒体

视觉格式化模型会根据 [CSS 盒子模型](/zh-CN/docs/Web/CSS/CSS_box_model/Introduction_to_the_CSS_box_model)将文档中的元素转换为一个个盒子,每个盒子的布局由以下因素决定
在视觉格式化模型中,文档树中的每个元素都会根据盒子模型生成一个个盒子。这些盒子的布局由以下因素决定

- 盒子的尺寸:精确指定、由约束条件指定或没有指定
- 盒子的类型:行内盒子(inline)、行内级盒子(inline-level)、原子行内级盒子(atomic inline-level)、块盒子(block)
- [定位方案(positioning scheme)](/zh-CN/docs/CSS/Box_positioning_scheme):普通流定位、浮动定位或绝对定位
- 文档树中的其他元素:即当前盒子的子元素或兄弟元素
- {{glossary("viewport", "视口")}}尺寸与位置
- 所包含的图片的尺寸
- 其他的某些外部因素
- 盒子的尺寸和类型。
- 定位方案(常规流定位、浮动定位和绝对定位)。
- 文档树中元素之间的关系。
- 外部因素(如,视口尺寸、图像的固有尺寸,等)。

该模型会根据盒子的包含块(*containing block)的*边界来渲染盒子。通常,盒子会创建一个包含其后代元素的包含块,但是盒子并不由包含块所限制,当盒子的布局跑到包含块的外面时称为溢出(_overflow)_
CSS2 中定义了许多有关视觉格式化模型的信息,但是不同的 CSS 布局模块已经扩展了这些信息。阅读规范时,你经常会发现对 CSS2 中定义的模型的引用。因此,在阅读其他布局规范时,了解该模型以及 CSS2 中用于描述该模型的术语很有价值

> [!NOTE]
> 译注:本文有很多相近的术语,阅读时需仔细,否则容易造成误解。为了方便读者,这里我将其整理一下。
>
> - **块**:block,一个抽象的概念,一个块在文档流上占据一个独立的区域,块与块之间在垂直方向上按照顺序依次堆叠。
> - **包含块**:containing 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 视觉格式化模型的一部分,用于从文档元素生成盒子。盒子有不同的类型,不同类型的盒子的格式化方法也有所不同。盒子的类型取决于 CSS {{ cssxref("display") }} 属性
在连续媒体中,{{glossary("viewport", "视口")}}是浏览器窗口的显示区域。当视口的尺寸发生改变时(例如,如果你改变窗口大小,或改变移动设备的屏幕方向),用户代理会改变页面的布局

### 块级元素与块盒子
如果视口小于文档的大小,那么用户代理需要提供一种方法来滚动到文档中不显示的部分。我们最常看到这种滚动是在**块向维度**上的滚动——在水平、从上到下的语言中的垂直滚动。但是,你可能设计了一些也需要在**行向维度**上滚动的内容。

当元素的 {{ cssxref("display") }} 为 `block`、`list-item` 或 `table` 时,该元素将成为块级元素。一个块级元素会被格式化成一个块(例如文章的一个段落),默认按照垂直方向依次排列。
## 盒子生成

每个块级盒子都会参与[块格式化上下文(block formatting context)](/zh-CN/docs/Web/CSS/CSS_display/Block_formatting_context)的创建,而每个块级元素都会至少生成一个块级盒子,即主块级盒子(_principal block-level_ *box)。有*一些元素,比如列表项会生成额外的盒子来放置项目符号,而那些会生成列表项的元素可能会生成更多的盒子。不过,多数元素只生成一个主块级盒子
**盒子生成**是 CSS 视觉格式化模型的一部分,用于从文档元素生成盒子。生成的盒子有不同的类型,影响它们视觉格式化的东西也不同。生成的盒子的类型取决于 CSS {{cssxref("display")}} 属性的值

主块级盒子包含由后代元素生成的盒子以及内容,同时它也会参与[定位方案](/zh-CN/docs/CSS/Positioning_scheme)
最初定义于 CSS2 中的 `display` 属性在 [CSS 显示模块第 3 版](https://www.w3.org/TR/css-display-3/)中得到了扩展。此外,自 CSS2 以来,一些与显示有关的术语已经得到更新和澄清

一个块级盒子可能也是一个块容器盒子。块容器盒子(*block container box)要么*只包含其他块级盒子,要么只包含行内盒子并同时创建一个行内[格式化上下文(inline formatting context)](/zh-CN/docs/CSS/Inline_formatting_context)
CSS 获取源文档并将其渲染到画布上。为此,它会生成一个中间结构,即**盒子树**,它表示被渲染文档的格式化结构。盒子树中的每一个盒子都表示画布上特定空间和/或时间点所对应的元素(或伪元素),而盒子树中的每个文本流同样表示其对应文本节点的内容

能够注意到块级盒子与块容器盒子是不同的这一点很重要。前者描述了元素与其父元素和兄弟元素之间的行为,而后者描述了元素跟其后代之间的行为。有些块级盒子并不是块容器盒子,比如表格;而有些块容器盒子也不是块级盒子,比如非替换行内块和非替换表格单元格
然后,对于每个元素,CSS 会根据元素 `display` 属性指定的值生成一个个盒子

一个同时是块容器盒子的块级盒子称为块盒子(_block box)。_
> [!NOTE]
> 盒子通常按其显示类型来指代——例如,由带有 `display: block` 的元素生成的盒子称为“块盒子”或简称为“块”。但请注意,块盒子、块级盒子和盒子容器之间具有细微的差异;有关更多星系信息,请参阅下面的[块盒子](#块盒子)部分。

### 主盒子

当一个元素生成了一个或多个盒子时,其中的一个盒子是**主盒子**(在盒子树中包含它的后代盒子和生成的内容,它同时也是任何定位方案中涉及的盒子)。

#### 匿名块盒子
一些元素可能会生成除主盒子以外的其他盒子,例如 `display: list-item` 会生成多个盒子(例如,一个**主块盒子**和一个**子标记盒子**)。而一些值(例如 `none` 或 `contents`)会导致元素及其后代不生成任何盒子。

### 匿名块盒子

在某些情况下进行视觉格式化时,需要添加一些增补性的盒子,这些盒子不能用 CSS 选择符选中,因此称为匿名盒子(_anonymous boxes)_。

CSS 选择器不能作用于匿名盒子 (_anonymous boxes_),所以它不能被样式表赋予样式。也就是说,此时所有可继承的 CSS 属性值都为 `inherit` ,而所有不可继承的 CSS 属性值都为 `initial`。

块包含盒子可能只包含行内级盒子,也可能只包含块级盒子,但通常的文档都会同时包含两者,在这种情况下,就会在相邻的行内级盒子外创建匿名块盒子。

{{EmbedGHLiveSample("css-examples/visual-formatting/anonymous-flex.html", '100%', 720)}}
```html live-sample___anonymous-flex
<div class="flex">
我被包装在一个匿名盒子中
<p>我在段落中</p>
我被包装在一个匿名盒子中。
</div>
```

```css live-sample___anonymous-flex
body {
font: 1.2em sans-serif;
margin: 20px;
}

.flex {
display: flex;
}

.flex > * {
background-color: rebeccapurple;
color: white;
}
```

{{EmbedLiveSample("anonymous-flex")}}

对这两个匿名盒子来说,程序员无法像 {{ HTMLElement("p") }} 元素那样控制它们的样式,因此它们会从 {{ HTMLElement("div") }} 那里继承那些可继承的属性,如 {{ cssxref("color") }}。其他不可继承的属性则会设置为 `initial`,比如,因为没有为它们指定 {{ cssxref("background-color") }},因此其具有默认的透明背景,而 `<p>` 元素的盒子则能够用 CSS 指定背景颜色。类似地,两个匿名盒子的文本颜色总是一样的。

另一种会创建匿名块盒子的情况是一个行内盒子中包含一或多个块盒子。此时,包含块盒子的盒子会拆分为两个行内盒子,分别位于块盒子的前面和后面。块盒子前面的所有行内盒子会被一个匿名块盒子包裹,块盒子后面的行内盒子也是一样。因此,块盒子将成为这两个匿名块盒子的兄弟盒子。

如果有多个块盒子,而它们中间又没有行内元素,则会在这些盒子的前面和后面创建两个匿名块盒子。

{{EmbedGHLiveSample("css-examples/visual-formatting/anonymous-block.html", '100%', 720)}}
```html live-sample___anonymous-block
<div class="example">
我被包装在一个匿名盒子中
<p>我在段落中</p>
我被包装在一个匿名盒子中。
</div>
```

```css live-sample___anonymous-block
body {
font: 1.2em sans-serif;
margin: 20px;
}

.example > * {
background-color: rebeccapurple;
color: white;
}
```

{{EmbedLiveSample("anonymous-block")}}

### 行内级元素和行内盒子

Expand All @@ -87,7 +117,33 @@ CSS 选择器不能作用于匿名盒子 (_anonymous boxes_),所以它不能
> [!NOTE]
> 开始的时候,原子行内级盒子叫做原子行内盒子,这并不准确,因为它们并不是行内盒子。后来在一次勘误时修正了这一问题。不过,当你见到某些文章中使用了“原子行内盒子”的时候,你尽可以将其理解为“原子行内级盒子”,因为这仅仅是一个名字的修改。

{{EmbedGHLiveSample("css-examples/visual-formatting/line-boxes.html", '100%', 720)}}
```html live-sample___line-boxes
<div class="float"></div>
<p class="following">
此文本跟随浮动,行级盒子被缩短以便为浮动腾出空间,但元素的盒子仍然在常规流中。
</p>
```

```css live-sample___line-boxes
body {
font: 1.2em sans-serif;
margin: 20px;
}

.float {
float: left;
width: 150px;
height: 150px;
background-color: rebeccapurple;
margin: 20px;
}

.following {
background-color: #ccc;
}
```

{{EmbedLiveSample("line-boxes", "", "250px")}}

#### 匿名行内盒子

Expand Down Expand Up @@ -167,6 +223,20 @@ Run-in 盒子通过 `display:run-in` 来定义,它可以是块盒子,也可

对固定位置的元素来说,其包含块为整个视口,该元素相对视口进行绝对定位,因此滚动时元素的位置并不会改变。

### 块级元素与块盒子

当元素的 {{ cssxref("display") }} 为 `block`、`list-item` 或 `table` 时,该元素将成为块级元素。一个块级元素会被格式化成一个块(例如文章的一个段落),默认按照垂直方向依次排列。

每个块级盒子都会参与[块格式化上下文](/zh-CN/docs/Web/CSS/CSS_display/Block_formatting_context)的创建,而每个块级元素都会至少生成一个块级盒子,即主块级盒子(_principal block-level_ *box)。有*一些元素,比如列表项会生成额外的盒子来放置项目符号,而那些会生成列表项的元素可能会生成更多的盒子。不过,多数元素只生成一个主块级盒子。

主块级盒子包含由后代元素生成的盒子以及内容,同时它也会参与[定位方案](/zh-CN/docs/CSS/Positioning_scheme)。

一个块级盒子可能也是一个块容器盒子。块容器盒子(*block container box)要么*只包含其他块级盒子,要么只包含行内盒子并同时创建一个行内[格式化上下文(inline formatting context)](/zh-CN/docs/CSS/Inline_formatting_context)。

能够注意到块级盒子与块容器盒子是不同的这一点很重要。前者描述了元素与其父元素和兄弟元素之间的行为,而后者描述了元素跟其后代之间的行为。有些块级盒子并不是块容器盒子,比如表格;而有些块容器盒子也不是块级盒子,比如非替换行内块和非替换表格单元格。

一个同时是块容器盒子的块级盒子称为块盒子(_block box)。_

## 参见

- CSS 重要概念:
Expand Down
Loading