使用 CSS display 的多关键字语法

The CSS display 模块 定义了 CSS display 属性的多关键字语法。本指南解释了多关键字语法。

注意:多关键字语法也称为“双值语法”或“多值语法”。

当我们更改 display 属性的值时会发生什么?

我们学习 CSS 时首先了解到的内容之一是,某些元素是块级元素,而某些元素是内联级元素。这些是它们的 外部 显示类型。例如,<h1><p> 默认情况下是块级元素,而 <span> 是内联级元素。使用 display 属性,我们可以在块级和内联级之间切换。例如,要使标题成为内联级,我们将使用以下 CSS

css
h1 {
  display: inline;
}

display 属性还允许我们在设置 display: griddisplay: flex 时使用 CSS 网格布局Flexbox。需要理解的重要概念是,更改元素的 display 值可以更改其直接子元素的格式化上下文。当您使用 display: flexdisplay: grid 时,元素的子元素将成为弹性项目或网格项目,并响应网格和 Flexbox 规范中的属性。

但是,网格和 Flexbox 演示了元素既具有外部显示类型又具有内部显示类型。外部显示类型描述元素是块级还是内联级。内部显示类型描述该框的子元素的行为方式。

例如,当我们使用 display: flex 时,我们创建了一个块级容器,其中包含弹性子元素。子元素被描述为参与弹性格式化上下文。如果您取一个 <span>(通常是内联级元素)并将其应用于 display: flex,则可以看到这一点。<span> 将变为块级元素。它在布局中与其他框的关系中表现得像块级元素一样。就好像您已将 display: block 应用于 span 一样,但是我们也获得了子元素行为的改变。

下面的实时示例具有一个应用了 display: flex<span>。它已成为一个块级框,占据了内联方向上所有可用的空间。您现在可以使用 justify-content: space-between 将此空间放在两个弹性项目之间。

还可以创建内联弹性容器。如果您使用单值 inline-flex,则将有一个内联级框,其中包含弹性子元素。子元素的行为方式与块级容器的弹性子元素相同。唯一改变的是父元素现在是一个内联级框。因此,它的行为类似于其他内联级元素,并且不占用块级框所占用的全部宽度(或内联尺寸中的大小)。这意味着某些后续文本可能会出现在弹性容器旁边。

在使用网格布局时也是如此。使用 display: grid 将为您提供一个块级框,该框为直接子元素创建网格格式化上下文。使用 display: inline-grid 将创建一个内联级框,该框为子元素创建网格格式化上下文。

使用多关键字语法

从以上说明可以看出,display 属性具有强大的功能。除了指示元素在页面上与其他框的关系中是块级还是内联级外,它还指示应用于它的框内部的格式化上下文。为了更好地描述此行为,display 属性允许在其中设置两个值——外部值和内部值。原始的单值语法也有效。

这意味着,我们不使用 display: flex 来创建具有弹性子元素的块级框,而是使用 display: block flex。不使用 display: inline-flex 来创建具有弹性子元素的内联级框,而是使用 display: inline flex。下面的示例演示了这些值。

display 的所有现有值都有映射;下表列出了最常用的值。要查看完整列表,请查看display 属性规范中的表格。

单值 多值
block block flow
flow-root block flow-root
inline inline flow
inline-block inline flow-root
flex block flex
inline-flex inline flex
grid block grid
inline-grid inline grid

display: block flow-root 和 display: inline flow-root

关于这种多值语法如何帮助阐明 CSS 布局,我们可以看看上表中一些您可能不太熟悉的 value。多关键字 display: block flow-root 映射到一个单值;display: flow-root。此 value 的唯一目的是创建一个新的块级格式化上下文 (BFC)。BFC 确保框内的一切都保留在框内,并且框外部的内容无法侵入其中。

在下面的示例中,两个 <p> 元素(一个在 <div> 内部)演示了 display 值如何影响格式化上下文。第一个带有演示控件的 <div> 元素被隐藏,以便我们可以专注于后续的元素。我们应该关注的元素是“父级”、“子级”和“兄弟”<div><p> 元素,您可以通过它们的 ID 区分它们。

此布局值得注意的一点是,父元素和子元素之间没有内容,并且子元素应用了顶部边距。您可能期望顶部边距有效地将子元素向下推入父元素内,但实际上发生的是称为边距折叠 的情况。在这种情况下,子元素的边距延伸到父元素的边界框之上,并将父元素进一步向下推到页面上。如果您检查子元素的盒模型在浏览器开发者工具中,则更容易看到这一点。

更改 <select> 元素中选定的选项以查看不同 display 值的效果。您可以使用任何带有 flow-root 的值来为父元素创建一个新的格式化上下文,使子元素边距相对于父元素的外边缘,并避免边距折叠。在 display: flow-rootdisplay: block flow-root 之间切换将获得与单值 flow-root 关键字相同的效果。

css
div,
p {
  outline: 2px solid black;
  background-color: cornflowerblue;
  display: block;
  margin-bottom: 2rem;
}

#parent {
  background-color: oldlace;
  min-height: 2rem;
}

#child {
  margin-top: 4rem;
  outline: 2px dashed red;
}

#sibling {
  background-color: lavender;
}
html
<div id="parent">
  <p id="child">The #child paragraph (nested in #parent).</p>
</div>
<p id="sibling">The #sibling paragraph (sibling of #parent).</p>

如果您考虑块级和内联布局(有时称为正常流),则 flow-root 值是有意义的。我们的 HTML 页面创建了一个新的格式化上下文(浮动和边距不能从边界扩展),并且我们的内容以正常流的方式布局,使用块级和内联布局,除非我们将 display 的值更改为使用其他格式化上下文。创建网格或弹性容器也会创建一个新的格式化上下文(分别为网格或弹性格式化上下文)。这些也包含它们内部的所有内容。但是,如果您想包含浮动和边距但继续使用块级和内联布局,您可以创建一个新的流根,并使用块级和内联布局重新开始。从那时起,所有内容都包含在新流根中。

这就是为什么 display: flow-root 可以使用多关键字语法 display: block flow-root 来编写的原因。您正在创建一个块级格式化上下文,其中包含一个块级框,并且子元素参与正常流。匹配对 display: inline flow-root 怎么样?这是描述 display: inline-block 的当前方式。

display: inline-block 值自 CSS 早期就存在。我们倾向于使用它的原因是,例如在创建导航项时,或像下面的示例中那样想要为内联元素添加带有填充的背景时,允许填充将内联项推离元素。

但是,具有 display: inline-block 的元素也将包含浮动。它包含内联级框内的所有内容。因此,display: inline-block 确实与 display: flow-root 执行相同的操作,但使用的是内联级框,而不是块级框。双值语法准确地描述了此 value 发生的情况。在上面的示例中,您可以将 display: inline-block 更改为 display: inline flow-root 并获得相同的结果。

旧的 display 值怎么样?

display 的单值在规范中被描述为旧值,目前您使用多关键字版本不会获得任何好处,因为每个多关键字版本都直接映射到旧版本,如上表所示。

为了处理 display 的单值,规范 解释了如果只使用 blockinline 的外部值该怎么办

“如果指定了 <display-outside> 值但省略了 <display-inside>,则元素的内部显示类型默认为 flow。”

这意味着行为与单值世界中的行为完全相同。如果您指定 display: blockdisplay: inline,则会更改框的外部显示值,但任何子元素都将继续以正常流的方式显示。如果只指定了 flexgridflow-root 的内部值,则规范 解释说外部值应设置为 block

“如果指定了 <display-inside> 值但省略了 <display-outside>,则元素的外部显示类型默认为 block——除了 ruby,它默认为 inline。”

最后,我们有一些旧的预组合内联级值

  • inline-block
  • inline-table
  • inline-flex
  • inline-grid

如果支持的浏览器将这些值作为单值遇到,则将其视为与多关键字版本相同

  • inline flow-root
  • inline table
  • inline flex
  • inline grid

因此,所有当前情况都得到了很好的涵盖,这意味着我们保持了使用单值的新旧站点的兼容性,同时允许规范发展。