CSS 网格布局模块第 2 级

W3C 候选推荐标准草案,

有关本文档的更多详细信息
此版本:
https://www.w3.org/TR/2025/CRD-css-grid-2-20250326/
最新发布版本:
https://www.w3.org/TR/css-grid-2/
编辑草案:
https://drafts.csswg.org/css-grid-2/
历史:
https://www.w3.org/standards/history/css-grid-2/
实现报告:
https://wpt.fyi/results/css/css-grid/subgrid
反馈:
CSSWG 问题库
CSSWG GitHub
规范内联问题
编辑:
Tab Atkins Jr. (Google)
Elika J. Etemad / fantasai (Apple)
(Microsoft)
(Igalia)
建议对此规范进行编辑:
GitHub 编辑器

摘要

此 CSS 模块定义了一个基于二维网格的布局系统,专为用户界面设计而优化。在网格布局模型中,网格容器的子元素可以定位到预定义的弹性或固定大小布局网格中的任意槽位。第 2 级通过为嵌套网格添加“子网格”功能来扩展网格,使其能够参与其父网格的尺寸确定。

CSS 是一种用于描述结构化文档(如 HTML 和 XML)在屏幕、纸张等媒介上渲染的语言。

本文档的状态

本节描述了本文档发布时的状态。 W3C 当前的出版物列表以及此技术报告的最新修订版可以在 W3C 标准和草案索引 https://www.w3.org/TR/ 中找到。

本文档由 CSS 工作组作为候选推荐标准草案发布,采用推荐标准制定流程。 作为候选推荐标准发布并不意味着 W3C 及其成员的认可。 候选推荐标准草案整合了先前候选推荐标准中的更改,工作组打算将其包含在后续的候选推荐标准快照中。

这是一份草案文件,可能随时被其他文件更新、替换或废弃。 将此文件引用为正在进行的工作以外的内容是不合适的。

请通过在 GitHub 中提交问题(首选)发送反馈, 并在标题中包含规范代码“css-grid”,例如: “[css-grid] …评论摘要…”。 所有问题和评论都已存档。 或者,可以将反馈发送到(已存档的)公共邮件列表 www-style@w3.org

本文档受 2023年11月3日 W3C 流程文档的约束。

本文档由一个在 W3C 专利政策下运作的小组制作。 W3C 维护一份与该小组交付成果相关的任何专利披露的公开列表; 该页面还包括披露专利的说明。 实际知晓某项专利包含基本权利要求的个人必须根据 W3C 专利政策第 6 节披露该信息。

如果您发现此网格布局模块与 弹性盒子布局模块 之间存在任何不一致之处,请向 CSSWG 报告,因为这很可能是一个错误。

1. 引言

本节不具有规范性。

网格布局是 CSS 的一种布局模型,它具有强大的功能来控制盒子及其内容的大小和定位。与弹性盒子布局(单轴导向)不同,网格布局针对二维布局进行了优化:即需要在两个维度上对齐内容的布局。

弹性布局示例:
                两行项目,
                第一行是三个项目,每个项目占据三分之一的空间,
                第二行是五个项目,每个项目占据五分之一的空间。
                因此,沿“行”对齐,但不沿“列”对齐。
代表性的弹性布局示例
网格布局示例:
                两行项目,
                第一行是四个项目——最后一个跨越两行,
                第二行是两个项目——第一个跨越前两列——加上第一行跨越的项目。
代表性的网格布局示例

此外,由于其能够显式地在网格中定位项目,网格布局允许在视觉布局结构上进行显著的转换,而无需相应的标记更改。通过将 媒体查询 与控制网格容器及其子元素布局的 CSS 属性相结合,作者可以使其布局适应设备外形、方向和可用空间的变化,同时在不同呈现方式中保持更理想的内容语义结构。

尽管许多布局可以用网格或弹性盒子来表达,但它们各有专长。网格强制执行二维对齐,采用自上而下的布局方法,允许项目显式重叠,并具有更强大的跨越能力。弹性盒子专注于轴内的空间分配,采用更简单的自下而上的布局方法,可以使用基于内容大小的换行系统来控制其次要轴,并依赖于底层的标记层次结构来构建更复杂的布局。预计两者都将成为 CSS 作者有价值且互补的工具。

网格第 2 级添加了 子网格 功能:子网格化的轴会将其网格线与元素父网格中的线对齐,并通过与父网格的这种集成来确定其轨道的尺寸。

1.1. 背景与动机

图片:需要水平和垂直对齐的应用程序布局示例。
需要水平和垂直对齐的应用程序布局示例。

随着网站从简单的文档演变为复杂的交互式应用程序,用于文档布局的技术(例如浮动)不一定非常适合应用程序布局。通过结合使用表格、JavaScript 或对浮动元素进行仔细测量,作者们发现了实现所需布局的变通方法。适应可用空间的布局通常很脆弱,并且在空间受限时会导致与直觉相反的行为。作为替代方案,许多 Web 应用程序的作者选择了固定布局,这种布局无法利用屏幕上可用渲染空间的变化。

网格布局的功能解决了这些问题。它为作者提供了一种机制,可以使用一组可预测的尺寸调整行为将可用于布局的空间划分为列和行。然后,作者可以将其应用程序的构建块元素精确地定位和调整到由这些列和行的交集定义的网格区域中。以下示例说明了网格布局的自适应功能,以及它如何实现内容和样式的更清晰分离。

1.1.1. 使布局适应可用空间

让我们考虑一个两列三行的游戏布局:游戏标题在左上角,菜单在其下方,分数在左下角,游戏板占据右上角和中间单元格,游戏控件填充左下角。左列的大小正好适合其内容(游戏标题、菜单项和分数),右列填充剩余空间。
根据内容大小和可用空间排列的五个网格项。
随着更大屏幕中可用空间的增加,允许中间行/右列扩展以填充该空间。
由于可用空间增加导致的网格增长。

网格布局可用于智能地调整网页内元素的大小。相邻的图表示一个包含五个主要布局组件的游戏:游戏标题、统计区域、游戏板、得分区域和控制区域。作者的意图是划分游戏空间,以便:

以下网格布局示例显示了作者如何以声明方式实现所有尺寸调整、放置和对齐规则。

/**
 * 通过在网格容器上声明网格,
 * 为每个网格项定义空间。
 */
#grid {
    /**
   * 两列:
   *  1. 第一列根据内容调整大小,
   *  2. 第二列获得剩余空间
   *     (但绝不小于游戏板的最小尺寸
   *     或占据此列的游戏控件 [图 4])
   *
   * 三行:
   *  3. 第一行根据内容调整大小,
   *  4. 中间行获得剩余空间
   *     (但绝不小于游戏板或统计区域的最小高度)
   *  5. 最后一行根据内容调整大小。
   */
    display: grid;
    grid-template-columns:
    /* 1 */ auto
    /* 2 */ 1fr;
    grid-template-rows:
    /* 3 */ auto
    /* 4 */ 1fr
    /* 5 */ auto;
}

/* 使用每个网格项的 'grid-row' 和 'grid-column' 属性上的坐标
 * 指定每个网格项的位置。
 */
#title    { grid-column: 1; grid-row: 1; }
#score    { grid-column: 1; grid-row: 3; }
#stats    { grid-column: 1; grid-row: 2; align-self: start; }
#board    { grid-column: 2; grid-row: 1 / span 2; }
#controls { grid-column: 2; grid-row: 3; justify-self: center; }
<div id="grid">
    <div id="title">游戏标题</div>
    <div id="score">得分</div>
    <div id="stats">统计</div>
    <div id="board">游戏板</div>
    <div id="controls">控件</div>
</div>

注意:有多种方法可以指定网格的结构以及定位和调整网格项的大小,每种方法都针对不同的场景进行了优化。

1.1.2. 源顺序独立性

图片:适合纵向方向的排列。
适合“纵向”方向的排列。
图片:适合横向方向的排列。
适合“横向”方向的排列。

继续前面的示例,作者还希望游戏能够适应不同的设备。此外,游戏应在纵向或横向查看时优化组件的放置(图 6 和图 7)。通过将网格布局与媒体查询相结合,作者能够使用相同的语义标记,但独立于其源顺序重新排列元素的布局,以在两种方向上实现所需的布局。

以下示例使用网格布局的功能来命名将由网格项占据的空间。这使得作者可以避免在网格定义更改时重写网格项的规则。

@media (orientation: portrait) {
    #grid {
    display: grid;

    /* 使用 grid-template-areas 属性直观地定义网格的行、列和区域。
     * 每个字符串是一行,每个单词是一个区域。字符串中单词的数量
     * 决定了列的数量。请注意,每个字符串中的单词数量必须相同。 */
    grid-template-areas: "title stats"
                            "score stats"
                            "board board"
                            "ctrls ctrls";

    /* 可以使用 grid-template-columns 和 grid-template-rows 属性
     * 分配调整列和行大小的方式。 */
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto 1fr auto;
    }
}

@media (orientation: landscape) {
    #grid {
    display: grid;

    /* 同样,template 属性定义了同名区域,
     * 但这次的位置不同,以更好地适应横向方向。 */
    grid-template-areas: "title board"
                            "stats board"
                            "score ctrls";

    grid-template-columns: auto 1fr;
    grid-template-rows: auto 1fr auto;
    }
}

/* grid-area 属性将网格项放置到网格的命名区域中。 */
#title    { grid-area: title }
#score    { grid-area: score }
#stats    { grid-area: stats }
#board    { grid-area: board }
#controls { grid-area: ctrls }
<div id="grid">
    <div id="title">游戏标题</div>
    <div id="score">得分</div>
    <div id="stats">统计</div>
    <div id="board">游戏板</div>
    <div id="controls">控件</div>
</div>

注意:网格布局的重新排序功能有意仅影响视觉呈现,而语音顺序和基于源顺序的导航则保持不变。这允许作者在保持源顺序完整且针对非 CSS UA 以及线性模型(如语音和顺序导航)进行优化的情况下操作视觉呈现。

网格项的放置和重新排序不得用作正确源排序的替代方法,因为这会破坏文档的可访问性。

1.2. 值定义

本规范遵循 [CSS2] 中的 CSS 属性定义约定,并使用 [CSS-VALUES-3] 中的值定义语法。 本规范中未定义的值类型在 CSS 值和单位 [CSS-VALUES-3] 中定义。 与其他 CSS 模块的组合可能会扩展这些值类型的定义。

除了在其定义中列出的特定于属性的值之外,本规范中定义的所有属性也接受 CSS 范围关键字作为其属性值。为便于阅读,未明确重复它们。

2. 概述

本节不具有规范性。

网格布局通过使用网格来控制其内容的布局: 一组相交的水平和垂直线,为网格容器的内容创建一个尺寸和定位坐标系。 网格布局的特性包括:

可以根据需要嵌套网格容器或将其与弹性容器混合使用,以创建更复杂的布局。

2.1. 声明网格

网格轨道)可以通过显式网格属性显式声明和调整大小,或者在项目放置在显式网格之外时隐式创建。 grid 简写属性及其子属性定义了网格的参数。 § 7 定义网格

以下是一些网格声明的示例:

2.2. 放置项目

网格容器的内容被组织成单独的网格项目(类似于弹性项目), 然后将这些项目分配给网格中预定义的区域。 它们可以通过网格放置属性使用坐标显式放置,或者使用自动放置隐式放置到空区域。 § 8 放置网格项目

以下是使用 grid-area 简写属性进行网格放置声明的一些示例:
grid-area: a;          /* 放置到名为“a”的网格区域     */
grid-area: auto;       /* 自动放置到下一个空区域    */
grid-area: 2 / 4;      /* 放置到第 2 行,第 4 列         */
grid-area: 1 / 3 / -1; /* 放置到第 3 列,跨越所有行 */
grid-area: header-start / sidebar-start / footer-end / sidebar-end;
                        /* 使用命名行进行放置            */

这些等效于以下 grid-row + grid-column 声明:

grid-row: a;                         grid-column: a;
grid-row: auto;                      grid-column: auto;
grid-row: 2;                         grid-column: 4;
grid-row: 1 / -1;                    grid-column: 3;
grid-row: header-start / footer-end; grid-column: sidebar-start / sidebar-end;

它们可以进一步分解为 grid-row-start/grid-row-end/grid-column-start/grid-column-end 完整属性,例如:

grid-area: a;
/* 等效于 grid-row-start: a; grid-column-start: a; grid-row-end: a; grid-column-end: a; */

grid-area: 1 / 3 / -1;
/* 等效于 grid-row-start: 1; grid-column-start: 3; grid-row-end: -1; grid-column-end: auto; */

2.3. 调整网格大小

一旦网格项目放置完毕, 就会计算网格轨道(行和列)的大小, 并根据网格定义中指定的其内容大小和/或可用空间进行调整。

根据网格容器align-contentjustify-content 属性,将调整大小后的网格在网格容器内进行对齐§ 11 对齐和间距

以下示例通过在列之间分配任何多余空间来对齐所有列, 并在网格小于 100vh 时将网格在网格容器中居中。
main {
    display: grid;
    grid: auto-flow auto / repeat(auto-fill, 5em);
    min-height: 100vh;
    justify-content: space-between;
    align-content: safe center;
}

最后,根据每个网格项目自身的尺寸调整 [CSS2]对齐属性 [CSS-ALIGN-3],在其分配的网格区域内调整其大小和对齐方式。

3. 网格布局概念和术语

网格布局中, 网格容器的内容通过将其定位和对齐到网格中进行布局。 网格是一组相交的水平和垂直网格线, 它将网格容器的空间划分为网格区域网格项目(代表网格容器的内容)可以放置在其中。 有两组网格线: 一组定义沿块轴延伸的, 另一组正交的线定义沿行内轴延伸的[CSS3-WRITING-MODES]

图片:网格线。
网格线:块轴三条,行内轴四条。

3.1. 网格线

网格线网格的水平和垂直分隔线。 网格线存在于列或行的两侧。 它们可以通过数字索引或作者指定的名称来引用。 网格项目使用网格放置属性引用网格线以确定其在网格中的位置。

以下两个示例都创建了三条列网格线和四条行网格线

第一个示例演示了作者如何使用网格线编号来定位网格项目

#grid {
  display: grid;
  grid-template-columns: 150px 1fr;
  grid-template-rows: 50px 1fr 50px;
}

#item1 { grid-column: 2;
         grid-row-start: 1; grid-row-end: 4; }

第二个示例使用显式命名的网格线

/* 与前一个示例等效的布局,但使用命名行 */
#grid {
  display: grid;
  grid-template-columns: 150px [item1-start] 1fr [item1-end];
  grid-template-rows: [item1-start] 50px 1fr 50px [item1-end];
}

#item1 {
  grid-column: item1-start / item1-end;
  grid-row: item1-start / item1-end;
}

3.2. 网格轨道和单元格

网格轨道网格列网格行的通用术语——换句话说,它是两条相邻网格线之间的空间。 每个网格轨道都被分配了一个尺寸调整函数, 该函数控制列或行的宽度或高度可以增长多少, 从而控制其边界网格线之间的距离。 相邻的网格轨道可以通过间距分隔,否则它们会紧密排列。

网格单元格是网格行和网格列的交集。 它是定位网格项目时可以引用的网格的最小单位。

在以下示例中,有两列三行。 第一列固定为 150px。 第二列使用弹性尺寸调整,这是网格中未分配空间的函数, 因此会随着网格容器宽度的变化而变化。 如果网格容器的已用宽度为 200px,则第二列的宽度为 50px。 如果网格容器的已用宽度为 100px,则第二列的宽度为 0px, 并且任何定位在该列中的内容都将溢出网格容器
#grid {
  display: grid;
  grid-template-columns: 150px 1fr;  /* 两列 */
  grid-template-rows: 50px 1fr 50px; /* 三行  */
}

3.3. 网格区域

网格区域是用于布局一个或多个网格项目的逻辑空间。 网格区域由一个或多个相邻的网格单元格组成。 它由四条网格线界定,网格区域的每一侧各有一条, 并参与其相交的网格轨道的尺寸调整。 网格区域可以使用网格容器grid-template-areas属性显式命名, 或通过其边界网格线隐式引用。 网格项目使用网格放置属性分配给网格区域

/* 使用模板语法 */
#grid  {
  display: grid;
  grid-template-areas: ". a"
                       "b a"
                       ". a";
  grid-template-columns: 150px 1fr;
  grid-template-rows: 50px 1fr 50px;
  height: 100vh;
}

#item1 { grid-area: a }
#item2 { grid-area: b }
#item3 { grid-area: b }

/* 将项目 2 和项目 3 对齐到网格区域“b”中的不同点。  */
/* 默认情况下,网格项目会拉伸以适应其网格区域    */
/* 并且这些项目会相互重叠。 */
#item2 { align-self: start; }
#item3 { justify-self: end; align-self: end; }

网格项目网格区域构成了其布局所在的包含块。放置在同一网格区域中的网格项目不会直接影响彼此的布局。 然而,间接地,占据具有固有尺寸调整函数网格轨道网格项目会影响该轨道的大小(从而影响其边界网格线的位置), 这反过来又会影响另一个网格项目的位置或大小。

3.4. 嵌套项与子网格项

网格项目本身可以通过为其指定 display: grid 来成为网格容器。 在一般情况下,此嵌套网格的内容布局将独立于其参与的父网格的布局。

然而,在某些情况下,可能需要多个网格项目的内容相互对齐。 嵌套网格可以将其行和/或列的定义延迟到其父网格容器, 使其成为子网格。 在这种情况下,子网格网格项目参与父网格的尺寸调整, 从而允许两个网格的内容对齐。 请参阅 § 9 子网格

子网格grid-template-rowsgrid-template-columnssubgrid 关键字建立, 并且可以在任一轴或两个轴上进行子网格化。 没有子网格化轴的网格是独立网格

例如,假设我们有一个表单,其中包含一个带有标签的输入列表:
<ul>
  <li><label>名称:</label> <input name=fn>
  <li><label>地址:</label> <input name=address>
  <li><label>电话:</label> <input name=phone>
</ul>

我们希望标签和输入对齐,并且希望为每个列表项设置边框样式。 这可以通过子网格布局来实现:

ul {
  display: grid;
  grid: auto-flow / auto 1fr;
}
li {
  grid-column: span 2;
  display: grid;
  grid-template-columns: subgrid;
  border: solid;
}
label {
  grid-column: 1;
}
input {
  grid-column: 2;
}

4. 重新排序和可访问性

网格布局赋予作者对文档进行重新排列的强大能力。 然而,这些并不能替代正确的文档源顺序。 order 属性和网格放置不会影响非可视化媒体(例如语音)中的顺序。 同样,在视觉上重新排列网格项目不会影响顺序导航模式的默认遍历顺序(例如循环浏览链接,参见例如 tabindex [HTML])。

作者必须仅将 order网格放置属性用于内容的视觉重新排序,而不是逻辑重新排序。 使用这些特性执行逻辑重新排序的样式表是不符合规范的。

注意:这样做是为了让通常以线性方式呈现内容的非可视化媒体和非 CSS UA 可以依赖于逻辑源顺序, 而网格布局的放置和排序特性则用于调整视觉排列。 (由于视觉感知是二维且非线性的, 因此期望的视觉顺序并不总是等同于期望的阅读顺序。)

许多网页在标记中具有相似的结构, 顶部是页眉, 底部是页脚, 中间是内容区域和一到两个附加列。 通常, 希望内容在附加列之前首先出现在页面的源代码中。 然而,这使得许多常见的设计, 例如简单地将附加列放在左侧,内容区域放在右侧, 难以实现。 多年来,这个问题已经通过多种方式得到解决, 当有两个附加列时,通常被称为“圣杯布局”。 网格布局使这个示例变得微不足道。 例如,采用以下页面代码和期望布局的草图:
<!DOCTYPE html>
<header>...</header>
<main>...</main>
<nav>...</nav>
<aside>...</aside>
<footer>...</footer>
在此页面中,页眉位于顶部,页脚位于底部,但主要内容位于中间,右侧是导航栏,左侧是侧边栏。

这种布局可以通过网格布局轻松实现:

body { display: grid;
        grid: "h h h"
                "a b c"
                "f f f";
        grid-template-columns: auto 1fr 20%; }
main    { grid-area: b; min-width: 12em;     }
nav     { grid-area: a; /* 自动最小宽度 */ }
aside   { grid-area: c; min-width: 12em;     }

另外一个好处是, 默认情况下,所有列的高度都将相等, 并且主要内容的宽度将足以填充屏幕。 此外, 这可以与媒体查询结合使用,以便在窄屏幕上切换到全垂直布局:

@media all and (max-width: 60em) {
    /* 太窄无法支持三列 */
    body { display: block; }
}

为了在所有呈现模式下保留作者预期的顺序, 创作工具——包括所见即所得编辑器以及基于 Web 的创作辅助工具——必须重新排序底层文档源, 并且不得使用 order网格放置属性来执行重新排序, 除非作者明确指出底层文档顺序(决定语音和导航顺序)应与视觉顺序不同步

例如,一个工具可能同时提供网格项目的拖放排列 以及针对不同屏幕尺寸范围的备用布局的媒体查询处理。

由于大多数情况下,重新排序应影响所有屏幕范围以及导航和语音顺序, 因此该工具将通过同时重新排序 DOM 层来匹配最终的拖放视觉排列。 然而,在某些情况下,作者可能希望每个屏幕尺寸具有不同的视觉排列。 该工具可以通过将网格放置属性与媒体查询结合使用来提供此功能, 但同时也将最小屏幕尺寸的排列与底层 DOM 顺序联系起来 (因为这很可能是逻辑线性呈现顺序), 同时使用网格放置属性在其他尺寸范围内重新排列视觉呈现。

这个工具是符合规范的,而一个只使用网格放置属性来处理拖放网格重新排列的工具 (无论以这种方式实现多么方便) 都是不符合规范的。

5. 网格容器

5.1. 建立网格容器:gridinline-grid display

名称: display
新值: grid | inline-grid
grid
此值使元素生成一个网格容器框,当放置在流式布局中时,该框是块级的。
inline-grid
此值使元素生成一个网格容器框,当放置在流式布局中时,该框是行内级的。

一个不是子网格网格容器为其内容建立一个独立的网格格式化上下文。 这与建立一个独立的块格式化上下文相同, 只是使用网格布局代替了块布局: 浮动不会侵入网格容器, 并且网格容器的外边距不会与其内容的外边距折叠。 网格容器的内容被布置到网格中, 网格线形成每个网格项目的包含块的边界。

与常规嵌套网格不同, 子网格的内容参与其父网格格式化上下文; 因此,子网格不会建立独立的格式化上下文

网格容器不是块容器, 因此一些在块布局假设下设计的属性在网格布局的上下文中不适用。 特别是:

如果元素的指定 displayinline-grid 并且该元素是浮动的或绝对定位的, 则 display 的计算值为 gridCSS 2.1 第 9.7 章中的表格因此被修改为包含一个额外的行, 其中“指定值”列为 inline-grid,“计算值”列为 grid

5.2. 调整网格容器大小

注意,有关本节术语的定义,请参见 [CSS-SIZING-3]

网格容器使用其参与的格式化上下文的规则进行大小调整:

在行内和块格式化上下文中, 网格容器自动块大小是其最大内容大小。

块布局规范可能应该定义这一点,但尚未编写。

网格容器最大内容大小最小内容大小)是当网格在最大内容约束最小内容约束)下调整大小时, 网格容器在相应轴上的轨道大小(包括间距)的总和。

5.3. 可滚动网格溢出

overflow 属性适用于网格容器

正如它包含在固有尺寸调整中(参见 § 5.2 调整网格容器大小), 网格也包含在网格容器可滚动溢出区域中。

注意:网格容器滚动容器时,请注意与内边距的交互: 定义了根据需要向可滚动溢出矩形添加额外的内边距, 以启用可滚动内容的 place-content: end 对齐。 请参见 CSS Overflow 3 § 2.2 可滚动溢出

5.4. 限制大型网格

由于内存有限, UA 可能会将隐式网格的可能大小限制在 UA 定义的限制内 (该限制应能容纳 [-10000, 10000] 范围内的行), 并删除超出该限制的所有行。 如果网格项目放置在此限制之外, 则其网格区域必须限制在此受限网格内。

限制网格区域

例如,如果 UA 仅支持每个维度最多包含 1000 个轨道的网格, 则以下放置属性:
.grid-item {
  grid-row: 500 / 1500;
  grid-column: 2000 / 3000;
}

最终将等效于:

.grid-item {
  grid-row: 500 / 1001;
  grid-column: 1000 / 1001;
}

6. 网格项目

不严格地说,网格容器网格项目是表示其常规流内容的框。

网格容器的每个常规流子元素都成为一个网格项目, 并且每个子文本序列都包裹在一个匿名块容器 网格项目中。 但是,如果文本序列仅包含空白(即可受 white-space 属性影响的字符), 则不会呈现它(就像其文本节点display:none 一样)。

网格项目示例:

<div style="display: grid">

    <!-- 网格项目:块级子元素 -->
    <div id="item1"></div>

    <!-- 网格项目:浮动元素;浮动被忽略 -->
    <div id="item2" style="float: left;">浮动</div>

    <!-- 网格项目:围绕内联内容的匿名块框 -->
    匿名项目3

    <!-- 网格项目:内联子元素 -->
    <span>
    项目4
    <!-- 网格项目不会围绕块分割 -->
    <q style="display: block" id=not-an-item>项目4</q>
    项目4
    </span>
</div>
从上面的代码块确定的网格项目
  1. 包含 的网格项目。
  2. 包含 浮动 的网格项目。
  3. (匿名,不可设置样式)包含 匿名项目3 的网格项目。
  4. 连续包含三个块的网格项目:
    • 包含 项目4 的匿名块。
    • 包含 项目4<q> 元素块。
    • 包含 项目4 的匿名块。

注意: 元素间的空白会消失: 它不会成为其自身的网格项目, 即使元素间的文本确实会被包裹在一个匿名网格项目中。

注意: 匿名项目的框是不可设置样式的, 因为没有元素可以分配样式规则。 但是,其内容将从网格容器继承样式(例如字体设置)。

6.1. 网格项目显示

除非是子网格, 否则网格项目会为其内容建立一个独立的格式化上下文。 但是,网格项目是 网格级 框,而不是块级框: 它们参与其容器的网格格式化上下文, 而不是块格式化上下文。

如果元素的最近祖先元素(跳过 display:contents 祖先)的计算 display 值为 gridinline-grid, 则元素自身的 display 值将被块化。 (有关此类 display 值转换的详细信息,请参阅 CSS2.1§9.7 [CSS2]CSS Display 3 § 2.7 自动框类型转换。)

注意: 即使 gridinline-grid 元素最终没有生成网格容器框(例如,当它被替换或在 display: none 子树中时),块化仍然会发生。

注意: display 的某些值通常会触发在原始框周围创建匿名框。 如果这样的框是网格项目, 则首先将其块化,因此不会发生匿名框创建。 例如,两个具有 display: table-cell 的连续网格项目将成为两个独立的 display: block 网格项目, 而不是被包裹到单个匿名表中。

6.2. 网格项目尺寸调整

网格项目在其网格区域定义的包含块内确定大小。

给定维度中网格项目自动大小的计算因其自对齐值而异:

正常

如果网格项目没有首选纵横比, 并且在相关轴上没有自然大小(如果是替换元素), 则网格项目的大小调整方式与 align-self: stretch 相同。

否则, 网格项目的大小调整与相应轴的块级元素的大小计算规则一致。 (请参阅 CSS 2 §  10 可视化格式模型详细信息。)

拉伸

对非替换框使用内联大小计算规则 (在 CSS 2 § 10.3.3 常规流中的块级非替换元素中定义), 即拉伸适应大小

注意: 如果具有首选纵横比的项目的尺寸在另一轴上也受到约束,这可能会扭曲其纵横比。

所有其他值

将项目大小调整为 fit-content

下表总结了网格项目的自动尺寸调整行为(仅供参考):
网格项目自动尺寸调整行为摘要
对齐 非替换元素大小 替换元素大小
正常 填充网格区域 使用自然大小
拉伸 填充网格区域 填充网格区域
start/center/等等。 fit-content 尺寸调整(类似于浮动) 使用自然大小

注意: automin-widthmin-height 会影响相关轴上的轨道尺寸调整,其方式类似于它影响弹性项目的主尺寸。 请参阅 § 6.6 网格项目的自动最小尺寸

6.3. 重新排序的网格项目:order 属性

order 属性也适用于网格项目。 它会影响它们的自动放置绘制顺序

与重新排序弹性项目一样, 仅当视觉顺序需要与语音和导航顺序不同步时才必须使用 order 属性; 否则应重新排序基础文档源。 请参阅 [CSS-FLEXBOX-1] 中的 CSS Flexbox 1 § 5.4.1 重新排序和可访问性

6.4. 网格项目外边距和内边距

由于相邻的网格项目独立地包含在其网格区域形成的包含块内, 因此相邻网格项目的外边距不会折叠

网格项目上的百分比外边距和内边距 (如块框上的那些), 是根据其包含块内联大小解析的, 例如,在水平书写模式下,左/右/上/下百分比都根据其包含块宽度进行解析。

自动外边距会扩展以吸收相应维度中的额外空间, 因此可用于对齐。 请参阅 § 11.2 使用自动外边距对齐

6.5. Z 轴排序:z-index 属性

网格项目被定位到相交的网格区域时, 或者由于负外边距或定位而被定位到不相交的区域时,它们可以重叠。 网格项目的绘制顺序与内联块 [CSS2]完全相同, 只是使用顺序修改的文档顺序代替原始文档顺序, 并且除 auto 之外的 z-index 值即使在 positionstatic 的情况下也会创建堆叠上下文(其行为与 positionrelative 完全一样)。 因此,z-index 属性可以轻松地用于控制网格项目的 Z 轴顺序。

注意:定位在网格项目外部的后代仍参与由网格项目建立的任何堆叠上下文。

下图显示了几个重叠的网格项目, 它们结合使用隐式源顺序和显式 z-index 来控制其堆叠顺序。
由 z-index 和源顺序控制的绘制顺序。
<style type="text/css">
#grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr
}
#A { grid-column: 1 / span 2; grid-row: 2; align-self: end; }
#B { grid-column: 1; grid-row: 1; z-index: 10; }
#C { grid-column: 2; grid-row: 1; align-self: start; margin-left: -20px; }
#D { grid-column: 2; grid-row: 2; justify-self: end; align-self: start; }
#E { grid-column: 1 / span 2; grid-row: 1 / span 2;
        z-index: 5; justify-self: center; align-self: center; }
</style>

<div id="grid">
    <div id="A">A</div>
    <div id="B">B</div>
    <div id="C">C</div>
    <div id="D">D</div>
    <div id="E">E</div>
</div>

6.6. 网格项目的自动最小尺寸

注意: 本节(以及规范的其余部分)中使用的大部分尺寸调整术语 在 CSS 内部和外部尺寸调整 [CSS-SIZING-3]中定义。

为了给网格项目提供更合理的默认最小尺寸, 如果在给定轴上其自动最小尺寸的使用值是基于内容的最小尺寸,则必须满足以下所有条件:

否则,自动最小尺寸通常为零。

注意: 基于内容的最小尺寸 是一种内部尺寸贡献, 因此适用 CSS Sizing 3 § 5.2 内部贡献中的规定。

在给定维度中,网格项目基于内容的最小尺寸是 其指定的尺寸建议(如果存在), 否则是其转移的尺寸建议(如果存在且元素被替换), 否则是其内容尺寸建议, 见下文。 但是, 如果在给定维度中 网格项目仅跨越具有固定最大轨道尺寸调整函数网格轨道, 则其在该维度中的指定的尺寸建议内容尺寸建议 (以及从此维度到相反维度中转移尺寸建议的输入) 将进一步被限制为小于或等于该维度中网格区域最大尺寸的拉伸适应值, 该值由这些网格轨道最大轨道尺寸调整函数之和加上任何中间的固定间距表示。

在所有情况下,如果受影响轴上的最大尺寸确定的,则尺寸建议还会受到该最大尺寸的限制。 如果项目是可压缩的替换元素, 并且在相关轴上具有确定的首选尺寸最大尺寸, 则尺寸建议将受这些尺寸的限制; 为此,这些尺寸中的任何不确定百分比都将根据零进行解析(并被视为确定的)。

注意: fit-content() 的参数不会像固定的最大轨道尺寸调整函数那样限制基于内容的最小尺寸

此计算中使用的内容尺寸建议指定的尺寸建议转移的尺寸建议考虑了相关的最小/最大/首选尺寸属性, 以便基于内容的最小尺寸不会干扰任何作者提供的约束, 定义如下:

指定的尺寸建议
如果项目在相关轴上的首选尺寸确定的, 则指定的尺寸建议就是该尺寸。 否则未定义。
转移的尺寸建议
如果项目具有首选纵横比并且其在相反轴上的首选尺寸确定的, 则转移的尺寸建议就是该尺寸 (如果相反轴的最小最大尺寸确定的,则受其限制), 并通过纵横比进行转换。 否则未定义。

如果项目在相关轴上具有确定的首选尺寸最大尺寸, 则转移的尺寸建议将受这些尺寸的限制; 为此,这些尺寸中的任何不确定百分比都将根据零进行解析(并被视为确定的)。

内容尺寸建议
内容尺寸建议是 相关轴上的最小内容尺寸, 如果它具有首选纵横比,则受通过纵横比转换的任何确定的相反轴最小最大尺寸的限制。

为了计算框的内部尺寸 (例如框的最小内容尺寸), 基于内容的最小尺寸会导致框在该轴上的尺寸变得不确定 (即使例如其 width 属性指定了确定的尺寸)。 请注意,这意味着根据此尺寸计算的百分比将表现为 auto

对于计算内部尺寸以外的任何目的, 基于内容的最小尺寸(与显式的 min-content/等 最小尺寸不同) 不会强制框的尺寸变得不确定。 但是,如果在应用此最小值之前根据框的尺寸解析了百分比, 则在应用之后必须根据新尺寸重新解析它。

请注意,虽然基于内容的最小尺寸通常是合适的, 并且有助于防止内容重叠或溢出其容器, 但在某些情况下并非如此:

特别是,如果网格布局用于文档的主要内容区域, 最好设置一个显式的字体相关最小宽度,例如 min-width: 12em。 基于内容的最小宽度可能导致大表格或大图像 拉伸整个内容区域的大小,可能进入溢出区域, 从而使文本行过长且难以阅读。

另请注意,当对具有大量内容的项目使用基于内容的尺寸调整时, 布局引擎必须遍历所有这些内容才能找到其最小尺寸, 而如果作者设置了显式最小值,则不需要这样做。 (但是,对于内容量较少的项目, 此遍历是微不足道的,因此不存在性能问题。)

7. 定义网格

7.1. 显式网格

这三个属性 grid-template-rowsgrid-template-columnsgrid-template-areas 共同定义了一个 显式网格,用于 网格容器,通过指定其 显式网格轨道。最终的网格可能由于 网格项 放置在 显式网格 之外而增大;在这种情况下,会创建隐式轨道,这些隐式轨道将由 grid-auto-rowsgrid-auto-columns 属性定义。

显式网格 的大小由 grid-template-areas 定义的行/列数 与 grid-template-rowsgrid-template-columns 定义的行/列数 中的较大者决定。任何由 grid-template-areas 定义但未由 grid-template-rowsgrid-template-columns 定义大小的行/列,其大小由 grid-auto-rowsgrid-auto-columns 属性决定。如果这些属性未定义 任何 显式 轨道,则 显式网格 在每个轴上仍包含一条 网格线

网格放置属性 中使用的数字索引从 显式网格 的边缘开始计数。正索引从 起始 侧计数(起始侧最先的显式线为 1),负索引从 结束 侧计数(结束侧最末的显式线为 -1)。

gridgrid-template 属性是 简写,可同时设置三个 显式网格属性grid-template-rowsgrid-template-columnsgrid-template-areas)。grid 简写还会重置控制 隐式网格 的属性,而 grid-template 则保持其不变。

7.2. 显式轨道尺寸调整:grid-template-rowsgrid-template-columns 属性

名称: grid-template-columnsgrid-template-rows
值: none | <track-list> | <auto-track-list> | subgrid <line-name-list>?
初始值: none
应用于: 网格容器
继承性:
百分比: 相对于内容区域的相应尺寸
计算值: 关键字 none计算后的轨道列表
规范顺序: 根据语法
动画类型: 如果列表长度匹配,则根据 计算后的轨道列表 中每项的计算值类型进行插值(参见 § 7.2.5 轨道列表的计算值§ 7.2.3.3 repeat() 的插值/组合);否则为离散动画。

这些属性以空格分隔的 轨道列表 的形式,指定 网格网格线名称轨道尺寸调整函数grid-template-columns 属性为网格的列指定 轨道列表,而 grid-template-rows 为网格的行指定 轨道列表

值的含义如下:

none
表示此属性不会创建任何 显式 网格轨道(尽管 显式网格 轨道仍可由 grid-template-areas 创建)。

注意:在没有 显式网格 的情况下,任何行/列都将 隐式生成,并且它们的大小将由 grid-auto-rowsgrid-auto-columns 属性确定。

<track-list> | <auto-track-list>
轨道列表 指定为一系列 轨道尺寸调整函数网格线名称。 每个 轨道尺寸调整函数 可以指定为长度、网格容器 大小的百分比、占据列或行的内容的度量,或网格中可用空间的一部分。它也可以使用 minmax() 表示法将其指定为一个范围,该表示法可以组合任何先前提及的机制,来为列或行指定单独的 最小最大轨道尺寸调整函数
subgrid <line-name-list>?
subgrid 值表示网格将采用其在该轴上的 父网格 的跨越部分(子网格化轴)。网格行/列的大小将从 父网格 的定义中获取,而不是显式指定,并且 子网格 的项目将参与与 父网格 共享的任何轨道的 固有尺寸计算CSS Grid Layout 1 § 11.5 解析固有轨道尺寸)。本质上,子网格 提供了将网格参数向下传递到嵌套元素,并将基于内容的尺寸信息向上传递回其 父网格 的能力。

<line-name-list> 参数允许对与 父网格 共享的网格线进行本地命名:如果给定了 <line-name-list>,则指定的 <line-names> 将分配给 子网格显式网格 的网格线,每条线一组,从第 1 条线开始。多余的 <line-names> 将被忽略。

如果没有 父网格,或者 网格容器 由于其他原因(例如,由于 布局包含 [CSS-CONTAIN-2]绝对定位 [CSS-POSITION-3])被迫建立 独立的格式化上下文,则 使用值 是初始值 none,并且 网格容器 不是 子网格

子网格化 的轴是 独立轴

轨道列表 的语法如下:

<track-list>          = [ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>?
<auto-track-list>     = [ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>? <auto-repeat>
                        [ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>?
<explicit-track-list> = [ <line-names>? <track-size> ]+ <line-names>?

<line-name-list>      = [ <line-names> | <name-repeat> ]+
<track-size>          = <track-breadth> | minmax( <inflexible-breadth> , <track-breadth> ) | fit-content( <length-percentage [0,∞]> )
<fixed-size>          = <fixed-breadth> | minmax( <fixed-breadth> , <track-breadth> ) | minmax( <inflexible-breadth> , <fixed-breadth> )
<track-breadth>       = <length-percentage [0,∞]> | <flex [0,∞]> | min-content | max-content | auto
<inflexible-breadth>  = <length-percentage [0,∞]> | min-content | max-content | auto
<fixed-breadth>       = <length-percentage [0,∞]>
<line-names>          = '[' <custom-ident>* ']'

其中组件值的定义如下…

7.2.1. 轨道尺寸

<length-percentage [0,∞]>
一个非负长度或百分比,由 CSS3 Values 定义。[CSS-VALUES-3]

<percentage> 值在列 网格轨道 中相对于 网格容器内部 内联尺寸,在行 网格轨道 中相对于 网格容器内部 块级尺寸。如果 网格容器 的大小取决于其轨道的大小,则为了计算 网格容器 的固有尺寸,<percentage> 必须被视为 auto,然后为了布局 网格 及其项目,根据最终的 网格容器 尺寸进行解析。

<flex [0,∞]>
一个带有单位 fr 的非负尺寸,指定轨道的 弹性因子。每个 <flex> 尺寸的轨道根据其 弹性因子 按比例分配剩余空间。例如,给定一个轨道列表 1fr 2fr,轨道将分别占据 剩余空间 的 ⅓ 和 ⅔。更多详情请参见 § 7.2.4 弹性长度:fr 单位

注意:如果 弹性因子 的总和小于 1,它们将只占据 剩余空间 的相应部分,而不是扩展以填充整个空间。

当出现在 minmax() 表示法之外时,表示一个自动最小值(即 minmax(auto, <flex>))。

minmax(min, max)
定义一个大于或等于 min 且小于或等于 max 的尺寸范围。如果 max 小于 min,则 max 将被 min 取下限(本质上产生 minmax(min, min))。作为最大值,<flex> 值设置轨道的 弹性因子;它作为最小值是无效的。

注意:本规范的未来版本可能允许 <flex> 最小值,并将更新 轨道尺寸调整算法 以正确处理此问题。

auto
作为最大值:表示占据 网格轨道网格项目 的最大 max-content 贡献;然而,与 max-content 不同,它允许通过 align-contentjustify-content 属性扩展轨道。

作为最小值:表示占据 网格轨道网格项目 的最大 最小尺寸(由 min-width/min-height 指定)。(这最初通常但不总是等于 min-content 最小值——参见 § 6.6 网格项目的自动最小尺寸。)

当出现在 minmax() 表示法之外时:等同于 minmax(auto, auto),表示上述最小值和最大值之间的范围。(在最基本的情况下,这与 minmax(min-content, max-content) 的行为类似,但具有额外的功能。)

max-content
表示占据 网格轨道网格项目 的最大 max-content 贡献
min-content
表示占据 网格轨道网格项目 的最大 min-content 贡献
fit-content( <length-percentage> )
表示公式 max(minimum, min(limit, max-content)),其中 minimum 表示一个 auto 最小值(通常但不总是等于 min-content 最小值),而 limit 是作为参数传递给 fit-content()轨道尺寸调整函数。这本质上是计算为 minmax(auto, max-content)minmax(auto, limit) 中的较小者。
给定以下 grid-template-columns 声明:
grid-template-columns: 100px 1fr max-content minmax(min-content, 1fr);

创建了五条网格线:

  1. 网格容器 的起始边缘。
  2. 距离 网格容器 起始边缘 100px。
  3. 距离前一条线的距离等于 可用空间 的一半(网格容器 的宽度减去非弹性 网格轨道 的宽度)。
  4. 距离前一条线的距离等于属于这两条线之间列的任何 网格项目 的最大尺寸。
  5. 距离前一条线的距离至少等于属于这两条线之间列的任何 网格项目 的最大最小尺寸,但不大于 可用空间 的另一半。

如果非弹性尺寸(100pxmax-contentmin-content)的总和大于 网格容器 的宽度,则最终的 网格线 将距离 网格容器 的起始边缘等于它们的总和(1fr 尺寸都解析为 0)。如果总和小于 网格容器 的宽度,则最终的 网格线 将恰好位于 网格容器 的结束边缘。只要 网格轨道 尺寸中至少有一个 <flex> 值,通常都是如此。

有效 网格轨道 定义的其他示例:
/* 有效轨道定义的示例 */
grid-template-rows: 1fr minmax(min-content, 1fr);
grid-template-rows: 10px repeat(2, 1fr auto minmax(30%, 1fr));
grid-template-rows: calc(4em - 5px);

注意:网格的大小并非纯粹是轨道大小的总和,因为 row-gapcolumn-gap 以及 justify-contentalign-content 可以在轨道之间添加额外的空间。

7.2.2. 命名网格线:[<custom-ident>*] 语法

虽然网格线总是可以通过其数字索引来引用,但网格线名称可以使网格放置属性更易于理解和维护。网格线名称可以通过 grid-template-rowsgrid-template-columns 属性显式分配,也可以通过 grid-template-areas 属性由命名网格区域隐式分配

例如,以下代码为网格中的所有线条赋予了有意义的名称。请注意,某些线条具有多个名称。
#grid {
    display: grid;
    grid-template-columns: [first nav-start] 150px [main-start] 1fr [last];
    grid-template-rows: [first header-start] 50px [main-start] 1fr [footer-start] 50px [last];
}
图片:命名的网格线。
命名的网格线。

网格线名称不能是 spanauto,即 <line-names> 产品中的 <custom-ident> 不包括关键字 spanauto

7.2.3. 重复行和列:repeat() 表示法

repeat() 表示法表示轨道列表的重复片段,允许以更紧凑的形式编写大量呈现重复模式的列或行。

此示例显示了编写相同网格定义的两种等效方法。两个声明都产生四个“主”列,每个列宽 250px,并由 10px 的“间距”列包围。
grid-template-columns: 10px [col-start] 250px [col-end]
                        10px [col-start] 250px [col-end]
                        10px [col-start] 250px [col-end]
                        10px [col-start] 250px [col-end] 10px;
/* 与上面相同,只是更容易编写 */
grid-template-columns: repeat(4, 10px [col-start] 250px [col-end]) 10px;
7.2.3.1. repeat() 的语法

repeat() 语法的通用形式大致如下:

repeat( [ <integer [1,∞]> | auto-fill | auto-fit ] , <track-list> )

第一个参数指定重复次数。第二个参数是一个轨道列表,该列表将重复指定的次数。但是,存在一些限制:

因此,repeat() 表示法的精确语法有几种形式:

<track-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <track-size> ]+ <line-names>? )
<auto-repeat>  = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
<fixed-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
<name-repeat> = repeat( [ <integer [1,∞]> | auto-fill ], <line-names>+)

如果一个不是 <name-repeat>repeat() 函数最终将两个 <line-names> 相邻放置,则名称列表将合并。例如,repeat(2, [a] 1fr [b]) 等效于 [a] 1fr [b a] 1fr [b]

7.2.3.2. 填充重复:auto-fillauto-fit 重复

子网格化轴上,auto-fill 关键字在每个 <line-name-list> 中仅有效一次,并且重复足够的次数以使名称列表与子网格指定的网格跨度匹配(如果跨度已满足,则回退到 0)。

否则,在独立轴上,当将 auto-fill 作为重复次数给出时,如果网格容器在相关轴上具有确定的 首选尺寸最大尺寸,则重复次数是不会导致网格溢出其网格容器内容框(考虑到间隙)的最大可能正整数;如果任何重复次数都会溢出,则重复 1 次。否则,如果网格容器在相关轴上具有确定的 最小尺寸,则重复次数是满足该最小要求的最小可能正整数。否则,指定的轨道列表仅重复一次。

为此,如果最大轨道尺寸调整函数确定的,则每个轨道被视为其最大轨道尺寸调整函数,否则,如果最小轨道尺寸调整函数是确定的,则为其最小轨道尺寸调整函数。如果两者都是确定的,则将最大轨道尺寸调整函数向下取整到最小轨道尺寸调整函数。如果两者都不是确定的,则重复次数为一。

例如,以下代码将创建尽可能多的 25 个字符宽的列以适应窗口宽度。如果还有剩余空间,它将被分配到 25 个字符宽的列中。
body {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(25ch, 1fr));
}

auto-fit 关键字的行为与 auto-fill 相同,只是在网格项放置之后,任何空的重复轨道都会折叠。空轨道是指没有在流中的网格项放置到其中或跨越它的轨道。(如果所有轨道都为空,这可能导致所有轨道都折叠。)

折叠的网格轨道被视为具有固定的 0px 轨道尺寸调整函数,并且其两侧的间距——包括通过分布式对齐分配的任何空间——都会折叠

为了在独立轴中找到自动重复轨道的数量,UA 必须将轨道大小向下取整到 UA 指定的值,以避免除以零。建议此下限为 1px

7.2.3.3. repeat() 的插值/组合

如果两个具有相同第一个参数(重复计数)和其第二个参数(轨道列表)中具有相同轨道数的 repeat() 表示法,则通过按计算值组合其计算轨道列表的每个组件来组合它们(就像组合顶级轨道列表一样)。否则它们离散地组合。

7.2.4. 弹性长度:fr 单位

弹性长度<flex> 是一个带有 fr 单位的维度,它表示 网格容器剩余空间的一部分。用 fr 单位确定尺寸的轨道称为弹性轨道,因为它们会响应剩余空间而伸缩,类似于具有零基本尺寸的弹性项目弹性容器中填充空间的方式。

剩余空间的分配发生在所有非弹性轨道尺寸调整函数达到其最大值之后。此类行或列的总大小从可用空间中减去,得到剩余空间,然后根据其弹性因子在弹性尺寸的行和列之间分配该剩余空间。

每列或每行在剩余空间中所占的份额可以计算为该列或行的 <flex> * <剩余空间> / <所有弹性因子的总和>

<flex> 值在 0fr 和 1fr 之间具有某种特殊的行为:当弹性因子的总和小于 1 时,它们将占据少于 100% 的剩余空间。

轨道的 <flex> 值实际上是对剩余空间某个比例的请求,其中 1fr 表示“100% 的剩余空间”;然后,如果该轴上的轨道总共请求超过 100%,则会重新平衡这些请求以保持相同的比例,但恰好用完 100% 的剩余空间。但是,如果轨道请求少于全部数量(例如三个轨道各为 .25fr),那么它们每个都将准确获得其请求的数量(每个轨道获得 25% 的剩余空间,最后 25% 未填充)。有关剩余空间如何分配的确切详细信息,请参见 § 12.7 扩展弹性轨道

fr 值接近零(这意味着轨道需要任何剩余空间)时,此模式对于连续行为是必需的。如果没有此模式,1fr 轨道将占据所有剩余空间;但 0.1fr 轨道和 0.01fr 轨道等也是如此,直到最终该值小到足以向下溢出为零,并且轨道突然不占据任何剩余空间。有了这种行为,当其弹性因子缩小到 1fr 以下时,轨道反而会逐渐占据更少的剩余空间,并在零时平稳地过渡到不占据任何剩余空间。

除非特别需要这种“部分填充”行为,否则作者应坚持使用 ≥ 1 的值;例如,使用 1fr2fr 通常比使用 .33fr.67fr 更好,因为如果添加或删除轨道,它们更有可能按预期运行。

当可用空间为无限大时(当网格容器的宽度或高度为不确定时),弹性尺寸的网格轨道将根据其内容调整大小,同时保持各自的比例。每个弹性尺寸网格轨道的已用大小是通过确定每个弹性尺寸网格轨道最大内容大小,然后将该大小除以各自的弹性因子来确定“假设的 1fr 大小”来计算的。这些值中的最大值用作已解析的 1fr 长度(弹性分数),然后将其乘以每个网格轨道弹性因子以确定其最终大小。

注意:<flex> 值不是 <length>(它们也不与<length>兼容,不像某些<percentage>值),因此它们不能在 calc() 表达式中表示或与其他单位类型组合。

7.2.5. 轨道列表的计算值

子网格轴的计算轨道列表是一个在网格线名称集轨道段之间交替的列表,第一个和最后一个项目是网格线名称集

网格线名称集是一个表示网格线名称的(可能为空的)有序集合

轨道段是以下任一项:

子网格轴的计算轨道列表subgrid 关键字,后跟一个网格线名称集计算重复表示法列表,表示为该轴指定的网格线名称。

7.2.6. 轨道列表的解析值

grid-template-rowsgrid-template-columns 属性是解析值特殊情况属性[CSSOM]

7.2.6.1. 独立轨道列表的解析值

当元素生成一个网格容器框时,其在独立轴中的 grid-template-rowsgrid-template-columns 属性的解析值已用值,序列化方式如下:

上述列表的第一点意味着隐式轨道作为 grid-template-rows/等的一部分进行序列化,尽管作者实际上无法在这些属性中指定隐式轨道大小!因此 grid-template-rowsgrid-template-columns 值可能无法正确往返:
const s = getComputedStyle(gridEl);
gridEl.style.gridTemplateRows = s.gridTemplateRows;
// 这样的代码应该是无操作的,
// 但是如果存在任何隐式行,
// 这会将它们转换为显式行,
// 可能会改变网格项的定位方式
// 并改变网格的整体大小!

这是一个早期实现的意外属性,在没有经过深思熟虑的情况下泄漏到后来的实现中。我们打算从规范中删除它,但要等到我们定义了用于获取有关隐式轨道信息的 CSSOM API 之后,因为目前这是获取该信息的唯一方法,并且许多页面都依赖于此。

否则(例如,当元素具有 display: none 或不是网格容器时),解析值只是计算值

<style>
#grid {
    width: 500px;
    grid-template-columns:
    [a]     auto
    [b]     minmax(min-content, 1fr)
    [b c d] repeat(2, [e] 40px)
            repeat(5, auto);
}
</style>
<div id="grid">
    <div style="grid-column-start: 1; width: 50px"></div>
    <div style="grid-column-start: 9; width: 50px"></div>
</div>
<script>
    var gridElement = document.getElementById("grid");
    getComputedStyle(gridElement).gridTemplateColumns;
    // [a] 50px [b] 320px [b c d e] 40px [e] 40px 0px 0px 0px 0px 50px
</script>

注意:通常,解析值是计算值,除了一小部分旧版 2.1 属性。但是,为了与此模块的早期实现兼容,我们需要将 grid-template-rowsgrid-template-columns 定义为返回已用值。

CSS 工作组正在考虑是否也为网格放置属性返回已用值,并正在征求反馈,尤其是来自实现者的反馈。请参阅讨论

7.2.6.2. 子网格轨道列表的解析值

当元素生成一个作为子网格网格容器框时,grid-template-rowsgrid-template-columns 属性的解析值表示已用的列数,序列化为 subgrid 关键字,后跟一个列表,该列表将其每条线表示为在子网格上显式定义的所有线的名称的网格线名称集(不包括从父网格采用的那些名称),而不使用 repeat() 表示法。

例如,当应用于具有 grid-column: span 4子网格时,以下每个 grid-template-columns 指定值都将成为相应的解析值
指定值: subgrid [a] repeat(auto-fill, [b]) [c]
解析值:  subgrid [a] [b] [b] [b] [c]
指定值: subgrid [a] [a] [a] [a] repeat(auto-fill, [b]) [c] [c]
解析值:  subgrid [a] [a] [a] [a] [c]
指定值: subgrid [] [a]
解析值:  subgrid [] [a] [] [] []
指定值: subgrid [a] [b] [c] [d] [e] [f]
解析值:  subgrid [a] [b] [c] [d] [e]

注意:这违反了一般的“最短等效序列化”原则,即通过序列化空的尾随网格线名称集,因为尾随网格线名称集提供了有关子网格跨越多少轨道的潜在有用信息。

7.3. 命名区域:grid-template-areas 属性

名称: grid-template-areas
值: none | <string>+
初始值: none
适用于: 网格容器
继承:
百分比: 不适用
计算值: 关键字 none 或字符串值列表
规范顺序: 按语法
动画类型: 离散

此属性指定命名网格区域,这些区域不与任何特定的网格项目关联,但可以从网格放置属性中引用。grid-template-areas 属性的语法还提供了网格结构的可视化,使网格容器的整体布局更易于理解。

值具有以下含义:

none
表示此属性未定义命名网格区域,同样也没有定义显式网格轨道(尽管显式网格轨道仍可由 grid-template-columnsgrid-template-rows 创建)。

注意:在没有显式网格的情况下,任何行/列都将隐式生成,其大小将由 grid-auto-rowsgrid-auto-columns 属性确定。

<string>+
grid-template-areas 属性列出的每个单独字符串创建一行,并为字符串中的每个单元格创建一列,解析如下:

使用最长匹配语义将字符串标记化为以下标记列表:

  • 标识符代码点序列,表示一个命名单元格标记,其名称由其代码点组成。
  • 一个或多个“.”(U+002E FULL STOP)的序列,表示一个空单元格标记
  • 空白序列,表示无内容(不生成标记)。
  • 任何其他字符序列,表示一个无效标记

注意:这些规则可以生成不匹配 <ident> 语法的单元格名称,例如 "1st 2nd 3rd",在其他属性中按名称引用这些区域时需要转义,例如 grid-row: \31st; 以引用名为 1st 的区域。

所有字符串必须定义相同数量的单元格标记(命名单元格标记和/或空单元格标记),并且至少有一个单元格标记,否则声明无效。如果一个命名网格区域跨越多个网格单元格,但这些单元格未形成单个填充的矩形,则声明无效。

注意:此模块的未来版本可能允许非矩形或不连续区域。

在此示例中,grid-template-areas 属性用于创建页面布局,其中为页眉内容 (head)、导航内容 (nav)、页脚内容 (foot) 和主要内容 (main) 定义了区域。因此,模板创建了三行两列,以及四个命名网格区域head 区域跨越网格的两列和第一行。
#grid {
    display: grid;
    grid-template-areas: "head head"
                        "nav  main"
                        "foot ...."
}
#grid > header { grid-area: head; }
#grid > nav    { grid-area: nav; }
#grid > main   { grid-area: main; }
#grid > footer { grid-area: foot; }

7.3.1. 模板字符串的序列化

当序列化 grid-template-areas<string> 值的指定值计算值时,每个空单元格标记序列化为单个“.” (U+002E FULL STOP),连续的单元格标记用单个空格 (U+0020 SPACE) 分隔,所有其他空白字符均被省略。

7.3.2. 隐式分配的网格线名称

grid-template-areas 属性从模板中的命名网格区域生成隐式分配的网格线名称。对于每个命名网格区域 foo,会创建四个隐式分配的网格线名称:两个名为 foo-start,命名命名网格区域的行开始线和列开始线,以及两个名为 foo-end,命名命名网格区域的行结束线和列结束线。

这些隐式分配的网格线名称的行为与任何其他网格线名称完全相同,只是它们不会出现在 grid-template-rows/grid-template-columns 的值中。即使定义了具有相同名称的显式分配的网格线名称隐式分配的网格线名称也只是具有相同名称的更多网格线。

7.3.3. 隐式命名区域

由于命名网格区域是通过其生成的隐式分配的网格线名称来引用的,因此显式添加相同形式的命名网格线 (foo-start/foo-end) 实际上会创建一个命名网格区域。这种隐式命名区域不会出现在 grid-template-areas 的值中,但仍可由网格放置属性引用。

7.4. 显式网格简写:grid-template 属性

名称: grid-template
值: none | [ <'grid-template-rows'> / <'grid-template-columns'> ] | [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?
初始值: none
适用于: 网格容器
继承: 参见各属性
百分比: 参见各属性
计算值: 参见各属性
动画类型: 参见各属性
规范顺序: 按语法

grid-template 属性是一个用于在单个声明中设置 grid-template-columnsgrid-template-rowsgrid-template-areas简写属性。它有几种不同的语法形式:

none
将所有三个属性设置为其初始值 (none)。
<'grid-template-rows'> / <'grid-template-columns'>
分别将 grid-template-rowsgrid-template-columns 设置为指定值,并将 grid-template-areas 设置为 none
grid-template: auto 1fr / auto 1fr auto;

等效于

grid-template-rows: auto 1fr;
grid-template-columns: auto 1fr auto;
grid-template-areas: none;
[ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?

这种语法允许作者将轨道名称和大小与其各自的网格区域内联对齐。

grid-template: [header-top] "a   a   a"     [header-bottom]
                    [main-top] "b   b   b" 1fr [main-bottom]
                            / auto 1fr auto;

等效于

grid-template-areas: "a a a"
                        "b b b";
grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
grid-template-columns: auto 1fr auto;

并创建以下网格:

CSS Grid 三列两行示意图
  • 三列,大小分别为 auto1frauto
  • 两行,大小分别为 auto1fr
  • 顶部一条名为 “header-top” 和 “a-start” 的线,中间一条具有四个名称——“header-bottom”、“main-top”、“a-end” 和 “b-start”——的线,底部一条名为 “main-bottom” 和 “b-end” 的线。
  • 左边缘一条名为 “a-start” 和 “b-start” 的线,右边缘一条名为 “a-end” 和 “b-end” 的线。
由上述声明创建的网格。(“a/b-start/end” 名称由命名网格区域隐式分配。)

注意:注意:repeat() 函数不允许在这些轨道列表(track listings)中使用,因为轨道(tracks)旨在与“ASCII艺术”中的行/列在视觉上一一对应。

注意:grid 简写属性接受相同的语法,但还会将隐式网格属性重置为其初始值。除非作者希望这些属性分别级联,因此建议使用 grid 而不是 grid-template

7.5. 隐式网格

grid-template-rowsgrid-template-columnsgrid-template-areas 属性定义了构成显式网格的固定数量的轨道。当网格项目被放置在这些边界之外时,网格容器通过向网格添加隐式网格线来生成隐式网格轨道。这些线与显式网格一起构成隐式网格grid-auto-rowsgrid-auto-columns 属性确定这些隐式网格轨道的大小,以及由 grid-template-areas 创建但未由 grid-template-rowsgrid-template-columns 显式确定大小的任何显式网格轨道的大小。

grid-auto-flow 属性控制没有显式位置的网格项目的自动放置。一旦显式网格被填满(或者如果没有显式网格),自动放置也将导致生成隐式网格轨道

grid 简写属性可以在单个声明中同时设置隐式网格属性grid-auto-flowgrid-auto-rowsgrid-auto-columns)和显式网格属性

7.6. 隐式轨道尺寸:grid-auto-rowsgrid-auto-columns 属性

名称: grid-auto-columnsgrid-auto-rows
值: <track-size>+
初始值: auto
适用于: 网格容器
继承:
百分比: 参见轨道尺寸
计算值: 参见轨道尺寸
规范顺序: 按语法
动画类型: 如果列表长度匹配,则按每个项目的计算值类型;否则为离散值

grid-auto-columnsgrid-auto-rows 属性指定未由 grid-template-rowsgrid-template-columns 分配大小的轨道的大小。如果给定了多个轨道大小,则根据需要重复该模式以找到受影响轨道的大小。最后一个显式确定大小的轨道之后的第一个轨道接收第一个指定的大小,依此类推;显式网格之前的最后一个隐式网格轨道接收最后一个指定的大小,依此类推。

注意:如果网格项目被放置到未由 grid-template-rows/grid-template-columns 和/或 grid-template-areas 显式声明的行或列中,则会创建隐式网格轨道来容纳它。这可以通过显式地将其放置到超出范围的行或列中,或者通过自动放置算法创建额外的行或列来实现。

<style>
    #grid {
    display: grid;
    grid-template-columns: 20px;
    grid-auto-columns: 40px;
    grid-template-rows: 20px;
    grid-auto-rows: 40px;
    }
    #A { grid-column: 1; grid-row: 1; }
    #B { grid-column: 2; grid-row: 1; }
    #C { grid-column: 1; grid-row: 2; }
    #D { grid-column: 2; grid-row: 2; }
</style>

<div id="grid">
    <div id="A">A</div>
    <div id="B">B</div>
    <div id="C">C</div>
    <div id="D">D</div>
</div>
一个 2×2 网格,第一行第一列有一个显式的 20px×20px 网格单元格,另外三个单元格是由于为容纳其他网格项目而生成的隐式 40px 列和行产生的。

7.7. 自动放置grid-auto-flow 属性

名称: grid-auto-flow
值: [ row | column ] || dense
初始值: row
适用于: 网格容器
继承:
百分比: 不适用
计算值: 指定的关键字
规范顺序: 按语法
动画类型: 离散

未显式放置的网格项目将由自动放置算法自动放置到网格容器中的未占用空间。grid-auto-flow 控制自动放置算法的工作方式,精确指定自动放置的项目如何流入网格。有关自动放置算法如何工作的精确详细信息,请参见 § 8.5 网格项目放置算法

row
自动放置算法通过依次填充每一行来放置项目,必要时添加新行。如果未提供 rowcolumn,则假定为 row
column
自动放置算法通过依次填充每一列来放置项目,必要时添加新列。
dense
如果指定,自动放置算法将使用“密集”打包算法,该算法会尝试填充网格中较早出现的空洞(如果稍后出现较小的项目)。当这样做可以填充较大项目留下的空洞时,可能会导致项目出现乱序。

如果省略,则使用“稀疏”算法,其中放置算法在放置项目时仅在网格中“向前”移动,从不回溯以填充空洞。这可确保所有自动放置的项目都“按顺序”出现,即使这会留下本可以由后续项目填充的空洞。

注意:此模块的未来级别预计会添加一个值,该值会将自动定位的项目一起流入单个“默认”单元格。

自动放置按顺序修改的文档顺序处理网格项目

在以下示例中,有三列,每列都根据其内容自动调整大小。没有显式定义行。grid-auto-flow 属性为 row,它指示网格从第一行开始搜索其三列,然后是下一行,根据需要添加行,直到找到足够的空间来容纳任何自动放置的网格项目的位置。
图片:使用自动放置排列的表单。

使用自动放置排列的表单。

<style type="text/css">
form {
    display: grid;
    /* 定义三列,全部根据内容调整大小,
        并命名相应的网格线。*/
    grid-template-columns: [labels] auto [controls] auto [oversized] auto;
    grid-auto-flow: row dense;
}
form > label {
    /* 将所有标签放置在 "labels" 列中,并
        自动查找下一个可用行。*/
    grid-column: labels;
    grid-row: auto;
}
form > input, form > select {
    /* 将所有控件放置在 "controls" 列中,并
        自动查找下一个可用行。*/
    grid-column: controls;
    grid-row: auto;
}

#department-block {
    /* 在 "oversized" 列中自动放置此项目
        在第一个行中,跨越三行的区域
        不会与其他显式放置的项目或区域
        或在此区域之前自动放置的任何项目重叠。*/
    grid-column: oversized;
    grid-row: span 3;
}

/* 将表单的所有按钮
    放置在显式定义的网格区域中。*/
#buttons {
    grid-row: auto;

    /* 确保按钮区域在内联轴上
        跨越整个网格元素。*/
    grid-column: 1 / -1;
    text-align: end;
}
</style>
<form>
    <label for="firstname">名字:</label>
    <input type="text" id="firstname" name="firstname">
    <label for="lastname">姓氏:</label>
    <input type="text" id="lastname" name="lastname">
    <label for="address">地址:</label>
    <input type="text" id="address" name="address">
    <label for="address2">地址 2:</label>
    <input type="text" id="address2" name="address2">
    <label for="city">城市:</label>
    <input type="text" id="city" name="city">
    <label for="state">州:</label>
    <select type="text" id="state" name="state">
    <option value="WA">华盛顿州</option>
    </select>
    <label for="zip">邮政编码:</label>
    <input type="text" id="zip" name="zip">

    <div id="department-block">
    <label for="department">部门:</label>
    <select id="department" name="department" multiple>
        <option value="finance">财务部</option>
        <option value="humanresources">人力资源部</option>
        <option value="marketing">市场部</option>
    </select>
    </div>

    <div id="buttons">
    <button id="cancel">取消</button>
    <button id="back">返回</button>
    <button id="next">下一步</button>
    </div>
</form>

7.8. 网格定义简写:grid 属性

名称: grid
值: <'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>
初始值: none
适用于: 网格容器
继承: 参见各属性
百分比: 参见各属性
计算值: 参见各属性
动画类型: 参见各属性
规范顺序: 按语法

grid 属性是一个简写属性,它在单个声明中设置所有显式网格属性grid-template-rowsgrid-template-columnsgrid-template-areas)和所有隐式网格属性grid-auto-rowsgrid-auto-columnsgrid-auto-flow)。(它不会重置间距属性。)

其语法与 grid-template 匹配,外加一种用于定义自动流网格的附加语法形式:

<'grid-template'>
grid-template 的完整属性设置为与 grid-template 相同,并将 grid-auto-* 的完整属性设置为其初始值。
<'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>?
[ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>
设置自动流,方法是显式设置一个轴中的轨道(将 grid-template-rowsgrid-template-columns 设置为指定值,并将另一个设置为 none),并指定如何在另一个轴中自动重复轨道(将 grid-auto-rowsgrid-auto-columns 设置为指定值,并将另一个设置为 auto)。grid-auto-flow 也相应地设置为 rowcolumn,如果指定了 dense,则包含 dense。

所有其他 grid 子属性都将重置为其初始值。

注意:请注意,您只能在单个 grid 声明中指定显式隐式网格属性。您未指定的子属性将设置为其初始值,这对于简写属性是正常的。

除了接受用于设置显式网格grid-template 简写语法外,grid 简写还可以轻松设置自动格式化网格的参数。例如,grid: auto-flow 1fr / 100px; 等效于
grid-template: none / 100px;
grid-auto-flow: row;
grid-auto-rows: 1fr;
grid-auto-columns: auto;

类似地,grid: none / auto-flow 1fr 等效于

grid-template: none;
grid-auto-flow: column;
grid-auto-rows: auto;
grid-auto-columns: 1fr;

序列化时,如果所有 grid-auto-* 完整属性都具有其初始值,则使用 grid-template 语法。

8. 放置网格项目

每个网格项都与一个网格区域相关联,该区域是网格项占据的一组相邻的矩形网格单元。此网格区域定义了网格项包含块,其中自对齐属性(justify-selfalign-self)确定其实际位置。网格项占据的单元格也会影响网格行和列的大小,这在 § 12 网格布局算法中定义。

网格项目网格区域网格中的位置由其放置定义,它由网格位置网格跨度组成:

网格位置
网格项目在每个轴上网格中的位置。网格位置可以是确定的(显式指定)或自动的(由自动放置确定)。
网格跨度
网格项目在每个轴上占据多少网格轨道。一个轴上的网格跨度可以是隐式的显式的自动的

网格放置属性——即完整属性 grid-row-startgrid-row-endgrid-column-startgrid-column-end 及其简写属性 grid-rowgrid-columngrid-area——允许作者通过提供以下六个信息中的任何一个(或不提供)来指定网格项目放置

开始 行开始线 列开始线
结束 行结束线 列结束线
跨度 行跨度 列跨度

在给定维度中,开始结束跨度中任意两个的确定值意味着第三个的确定值。

8.1. 网格放置的常见模式

本节内容仅供参考。

网格放置属性的完整属性被组织成三个简写属性:

grid-area
grid-column grid-row
grid-column-start grid-column-end grid-row-start grid-row-end

8.1.1. 命名区域

通过在 grid-area 中指定区域名称,可以将项目放置到命名网格区域(例如由 grid-template-areas 中的模板生成的区域):

article {
    grid-area: main;
    /* 将项目放置到名为 "main" 的区域。*/
}

项目也可以与命名网格区域部分对齐,其他边缘与某个其他线对齐:

.one {
    grid-row-start: main;
    /* 将行开始边缘与 "main" 命名区域的开始边缘对齐。*/
}

8.1.2. 数字索引和跨度

网格项目可以通过数字进行定位和调整大小,这对于脚本驱动的布局特别有用:

.two {
    grid-row: 2;    /* 将项目放置在第二行。*/
    grid-column: 3; /* 将项目放置在第三列。*/
    /* 等效于 grid-area: 2 / 3; */
}

默认情况下,网格项目的跨度为 1。可以显式指定不同的跨度:

.three {
    grid-row: 2 / span 5;
    /* 从第 2 行开始,
        向下跨越 5 行(在第 7 行结束)。*/
}

.four {
    grid-row: span 5 / 7;
    /* 在第 7 行结束,
        向上跨越 5 行(从第 2 行开始)。*/
}

注意:请注意,网格索引是与书写模式相关的。例如,在像阿拉伯语这样的从右到左的语言中,第一列是最右边的列。

8.1.3. 命名线和跨度

可以按线名称引用线,而不是按数字计数:

.five {
    grid-column: first / middle;
    /* 从名为 "first" 的线跨越到名为 "middle" 的线。*/
}

注意:请注意,如果命名网格区域线名称同名,则放置算法将优先使用命名网格区域的线。

如果有多条同名的线,它们有效地建立了一个命名的网格线集,可以通过按名称筛选放置来专门索引:

.six {
    grid-row: text 5 / text 7;
    /* 在名为 "text" 的第 5 条线和第 7 条线之间跨越。*/
    grid-row: text 5 / span text 2;
    /* 与上面相同 - 从名为 "text" 的第 5 条线开始,
        然后跨越另外两条 "text" 线,到达第 7 条。*/
}

8.1.4. 自动放置

网格项目可以自动放置到下一个可用的空网格单元格中,如果空间不足,则会扩展网格

.eight {
    grid-area: auto; /* 初始值 */
}

例如,这可以用于在目录网站上以网格模式列出许多促销商品。

如果项目应占用多个单元格,则自动放置可以与显式跨度结合使用:

.nine {
    grid-area: span 2 / span 3;
    /* 自动放置的项目,覆盖两行三列。*/
}

自动放置算法是跨行搜索并添加行,还是跨列搜索并添加列,由 grid-auto-flow 属性控制。

注意:默认情况下,自动放置算法会线性地遍历网格而不回溯;如果为了放置较大的项目而必须跳过一些空格,它不会返回以填充这些空格。要更改此行为,请在 grid-auto-flow 中指定 dense 关键字。

8.2. 网格项目放置与源顺序

“能力越大,责任越大。”

网格放置属性的功能允许内容在网格内自由排列和重新排序,这样视觉呈现就可以在很大程度上与基础文档源顺序分离。这些功能为作者提供了极大的自由度,可以针对不同的设备和表示模式(例如使用媒体查询)定制渲染。然而,它们不能替代正确的源顺序

正确的源顺序对于语音、顺序导航(例如键盘导航)以及非 CSS 用户代理(如搜索引擎、触觉浏览器等)非常重要。网格放置影响视觉呈现!这允许作者针对非 CSS/非视觉交互模式优化文档源,并使用网格放置技术进一步操作视觉呈现,从而保持源顺序不变。

8.3. 基于线的放置:grid-row-startgrid-column-startgrid-row-endgrid-column-end 属性

名称: grid-row-startgrid-column-startgrid-row-endgrid-column-end
值: <grid-line>
初始值: auto
适用于: 网格项目以及其包含块是网格容器的绝对定位框
继承:
百分比: 不适用
计算值: 指定的关键字、标识符和/或整数
规范顺序: 按语法
动画类型: 离散
<grid-line> =
    auto |
    <custom-ident> |
    [ [ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>? ] |
    [ span && [ <integer [1,∞]> || <custom-ident> ] ]

grid-row-startgrid-column-startgrid-row-endgrid-column-end 属性通过向其网格放置贡献一条线、一个跨度或什么都不贡献(自动),从而确定网格项目网格中的大小和位置,从而指定其网格区域行内起始块起始行内结束块结束边缘。

值的含义如下:

<custom-ident>
首先尝试将网格区域的边缘与命名网格区域匹配:如果存在一条网格线,其线名称<custom-ident>-start(对于 grid-*-start)/ <custom-ident>-end(对于 grid-*-end),则将第一条这样的线贡献给网格项目放置

注意:命名网格区域会自动生成这种形式的隐式分配的线名称,因此指定 grid-row-start: foo 将选择该命名网格区域的起始边缘(除非在此之前显式指定了另一条名为 foo-start 的线)。

否则,将其视为已随 <custom-ident> 一起指定了整数 1

[ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>?
将第 N网格线贡献给网格项目放置。如果给定负整数,则从显式网格的结束边缘开始反向计数。

如果以 <custom-ident> 的形式给出了名称,则仅计算具有该名称的线。如果具有该名称的线不足,则假定所有隐式网格线都具有该名称以查找此位置。

<integer> 值为零会使声明无效。

span && [ <integer [1,∞]> || <custom-ident> ]
网格项目放置贡献一个网格跨度,使得网格项目网格区域的相应边缘距离其相对边缘 N 条线(在相应方向上)。例如,grid-column-end: span 2 表示从 grid-column-start 线开始,在结束方向上的第二条网格线。

如果以 <custom-ident> 的形式给出了名称,则仅计算具有该名称的线。如果具有该名称的线不足,则假定显式网格一侧(对应于搜索方向)的所有隐式网格线都具有该名称以计算此跨度。

例如,给定以下声明:
.grid { grid-template-columns: 100px; }
.griditem { grid-column: span foo / 4; }

网格容器具有一个显式网格,其中包含两条网格线,编号为 1 和 2。网格项目的列结束边缘指定为第 4 条线,因此在隐式网格的结束侧生成了两条线。

其列开始边缘必须是它在该位置的起始方向上能找到的第一条“foo”线。但是,网格中没有“foo”线,因此唯一的可能性是隐式网格中的一条线。第 3 条线不是候选线,因为它位于显式网格的结束侧,而 grid-column-start 跨度强制它向起始方向搜索。因此,唯一的选择是让隐式网格显式网格的起始侧生成一条线。

结果图示。
结果图示。

如果省略 <integer>,则默认为 1。负整数或零无效。

auto
该属性对网格项目放置没有任何贡献,表示自动放置或默认跨度为 1。(参见上面的 § 8 放置网格项目。)

在上述所有产生式中,<custom-ident> 还排除了关键字 spanauto

给定一个单行 8 列的网格和以下 9 条命名线:
1  2  3  4  5  6  7  8  9
+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |
A  B  C  A  B  C  A  B  C
|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+

以下声明将网格项目放置在索引指示的线之间:

grid-column-start: 4; grid-column-end: auto;
/* 线 4 到线 5 */

grid-column-start: auto; grid-column-end: 6;
/* 线 5 到线 6 */

grid-column-start: C; grid-column-end: C -1;
/* 线 3 到线 9 */

grid-column-start: C; grid-column-end: span C;
/* 线 3 到线 6 */

grid-column-start: span C; grid-column-end: C -1;
/* 线 6 到线 9 */

grid-column-start: span C; grid-column-end: span C;
/* 错误:结束跨度被忽略,自动放置的
    项目不能跨越到命名线。
    等效于 ''grid-column: span 1;''。*/

grid-column-start: 5; grid-column-end: C -1;
/* 线 5 到线 9 */

grid-column-start: 5; grid-column-end: span C;
/* 线 5 到线 6 */

grid-column-start: 8; grid-column-end: 8;
/* 错误:线 8 到线 9 */

grid-column-start: B 2; grid-column-end: span 1;
/* 线 5 到线 6 */

8.3.1. 网格放置冲突处理

如果网格项目放置包含两条线,并且起始线比结束线更靠后,则交换这两条线。如果起始线等于结束线,则移除结束线。

如果放置包含两个跨度,则移除由结束网格放置属性贡献的那个跨度。

如果放置仅包含命名线的跨度,则将其替换为跨度 1。

8.4. 放置简写:grid-columngrid-rowgrid-area 属性

名称: grid-rowgrid-column
值: <grid-line> [ / <grid-line> ]?
初始值: auto
适用于: 网格项目以及其包含块是网格容器的绝对定位框
继承:
百分比: 不适用
计算值: 参见各属性
动画类型: 离散
规范顺序: 按语法

grid-rowgrid-column 属性分别是 grid-row-start/grid-row-endgrid-column-start/grid-column-end 的简写。

如果指定了两个 <grid-line> 值,则 grid-row-start/grid-column-start 完整属性设置为斜杠前的值,而 grid-row-end/grid-column-end 完整属性设置为斜杠后的值。

当省略第二个值时,如果第一个值是 <custom-ident>,则 grid-row-end/grid-column-end 完整属性也设置为该 <custom-ident>;否则,它设置为 auto

名称: grid-area
值: <grid-line> [ / <grid-line> ]{0,3}
初始值: auto
适用于: 网格项目以及其包含块是网格容器的绝对定位框
继承:
百分比: 不适用
计算值: 参见各属性
动画类型: 离散
规范顺序: 按语法

grid-area 属性是 grid-row-startgrid-column-startgrid-row-endgrid-column-end简写

如果指定了四个 <grid-line> 值,则 grid-row-start 设置为第一个值,grid-column-start 设置为第二个值,grid-row-end 设置为第三个值,而 grid-column-end 设置为第四个值。

当省略 grid-column-end 时,如果 grid-column-start<custom-ident>,则 grid-column-end 设置为该 <custom-ident>;否则,它设置为 auto

当省略 grid-row-end 时,如果 grid-row-start<custom-ident>,则 grid-row-end 设置为该 <custom-ident>;否则,它设置为 auto

当省略 grid-column-start 时,如果 grid-row-start<custom-ident>,则所有四个完整属性都设置为该值。否则,它设置为 auto

注意:此简写的解析顺序是 row-start/column-start/row-end/column-end,对于 LTR 页面,这是逆时针方向,与使用物理方向的相关 4 边属性(如 margin)的方向相反。

8.5. 网格项目放置算法

以下网格项目放置算法网格项目自动位置解析为确定位置,确保每个网格项目都有一个明确定义的网格区域以供布局。(网格跨度不需要特殊解析;如果未显式指定,则默认为 1。)

注意:如果在显式网格中没有空间放置自动定位的网格项目,此算法可能会导致在隐式网格中创建新的行或列。

每个网格单元格(在显式隐式网格中)都可以是已占用未占用。如果一个单元格被具有确定网格位置网格项目网格区域覆盖,则该单元格为已占用;否则,该单元格为未占用。单元格的已占用/未占用状态在此算法执行期间可能会发生变化。

为清楚起见,此算法的编写假设 grid-auto-flow 已指定为 row。如果将其设置为 column,则在此算法中交换所有提及的行和列、内联和块等。

注意:自动放置算法处理网格项目时,采用的是顺序修改后的文档顺序,而不是其原始文档顺序。

  1. 生成匿名网格项目,如 § 6 网格项目中所述。(匿名网格项目始终是自动放置的,因为它们的框不能指定任何网格放置属性。)

  2. 定位所有非自动定位的项目。

  3. 处理锁定到给定行的项目。

    对于每个具有确定行位置网格项目(即 grid-row-startgrid-row-end 属性定义了一个确定网格位置),按照顺序修改后的文档顺序

    “稀疏”打包(默认行为)

    将其放置的列起始线设置为最早(最小正索引)的线索引,以确保此项目的网格区域不会与任何已占用的网格单元格重叠,并且位于此步骤中先前放置在此行中的任何网格项目之后。

    “密集”打包(指定了 dense

    将其放置的列起始线设置为最早(最小正索引)的线索引,以确保此项目的网格区域不会与任何已占用的网格单元格重叠。

  4. 确定隐式网格中的列。

    隐式网格中创建列:

    1. 显式网格中的列开始。

    2. 在所有具有确定列位置的项目(显式定位的项目、上一步中定位的项目以及尚未定位但具有确定列的项目)中,根据需要向隐式网格的开头和结尾添加列以容纳这些项目。

    3. 如果所有没有确定列位置的项目中最大的列跨度大于隐式网格的宽度,则向隐式网格的末尾添加列以容纳该列跨度

    例如,在以下样式片段中:
    #grid {
        display: grid;
        grid-template-columns: repeat(5, 100px);
        grid-auto-flow: row;
    }
    #grid-item {
        grid-column: 4 / span 3;
    }
    

    所需的列数为 6。显式网格提供了 5 列(来自 grid-template-columns),线号从 1 到 6,但是 #grid-item 的列位置意味着它结束于第 7 条线,这需要在隐式网格的末尾添加额外的列。

  5. 定位剩余的网格项目。

    自动放置光标定义了网格中当前的“插入点”,指定为一对行和列网格线。最初,自动放置光标设置在隐式网格中最开始的行和列线。

    正在使用的 grid-auto-flow 值决定了如何定位项目:

    “稀疏”打包(默认行为)

    对于每个尚未通过先前步骤定位的网格项目,按照顺序修改后的文档顺序

    如果项目具有确定的列位置
    1. 光标的列位置设置为网格项目的列起始线。如果这小于光标先前的列位置,则将行位置增加 1。

    2. 增加光标的行位置,直到找到一个值,使得网格项目不与任何已占用的网格单元格重叠(必要时在隐式网格中创建新行)。

    3. 将项目的行起始线设置为光标的行位置,并根据其从该位置的跨度设置项目的行结束线。

    如果项目在两个轴上都具有自动网格位置
    1. 增加自动放置光标的列位置,直到此项目的网格区域不与任何已占用的网格单元格重叠,或者光标的列位置加上项目的列跨度超出此算法先前确定的隐式网格中的列数。

    2. 如果在上一步中找到了不重叠的位置,则将项目的行起始线和列起始线设置为光标的位置。否则,增加自动放置光标的行位置(必要时在隐式网格中创建新行),将其列位置设置为隐式网格中最开始的列线,然后返回上一步。

    “密集”打包(指定了 dense

    对于每个尚未通过先前步骤定位的网格项目,按照顺序修改后的文档顺序

    如果项目具有确定的列位置
    1. 将光标的行位置设置为隐式网格中最开始的行线。将光标的列位置设置为网格项目的列起始线。

    2. 增加自动放置光标的行位置,直到找到一个值,使得网格项目不与任何已占用的网格单元格重叠(必要时在隐式网格中创建新行)。

    3. 将项目的行起始线索引设置为光标的行位置。(也隐式地根据其跨度设置项目的行结束线。)

    如果项目在两个轴上都具有自动网格位置
    1. 将光标的行和列位置设置为隐式网格中最开始的行和列线。

    2. 增加自动放置光标的列位置,直到此项目的网格区域不与任何已占用的网格单元格重叠,或者光标的列位置加上项目的列跨度超出此算法先前确定的隐式网格中的列数。

    3. 如果在上一步中找到了不重叠的位置,则将项目的行起始线和列起始线设置为光标的位置。否则,增加自动放置光标的行位置(必要时在隐式网格中创建新行),将其列位置重置为隐式网格中最开始的列线,然后返回上一步。

9. 子网格

子网格的行为与普通网格容器完全相同,只是:

10. 绝对定位

10.1. 以网格容器作为包含块

如果绝对定位元素的包含块网格容器生成,则包含块对应于由其网格放置属性确定的网格区域。偏移属性(top/right/bottom/left)随后像往常一样指示从此包含块的相应边缘向内的偏移量。

注意:虽然将元素绝对定位到网格容器确实允许它与该容器的网格线对齐,但此类元素不占用空间或以其他方式参与网格的布局。

.grid {
    grid: 1fr 1fr 1fr 1fr / 10rem 10rem 10rem 10rem;
    /* 4 个等高行填充网格容器,
        4 列,每列 ''10rem'' */
    justify-content: center;
    /* 在网格容器内水平居中网格 */
    position: relative;
    /* 建立绝对定位包含块 */
}

.abspos {
    grid-row-start: 1;     /* 第 1 条网格行线 = 网格容器顶部 */
    grid-row-end: span 2;  /* 第 3 条网格行线 */
    grid-column-start: 3;  /* 第 3 条网格列线 */
    grid-column-end: auto; /* 右内边距边缘 */
    /* 包含块覆盖网格容器的右上象限 */

    position: absolute;
    top: 70px;
    bottom: 40px;
    left: 100px;
    right: 30px;
}
绝对定位网格示例图

注意:网格和网格放置属性流相对的,而偏移属性(leftrighttopbottom)是物理的,因此如果 directionwriting-mode 属性发生更改,网格将进行转换以匹配,但偏移量不会。

对于网格放置属性auto 值,它不会进行自动放置,而是为放置贡献一条特殊线,其位置是网格容器相应内边距边缘的位置(如果网格容器溢出,则为可滚动区域的内边距边缘)。这些线成为用于定位绝对定位项目的增强网格的第一条和最后一条线(第 0 条和第 -0 条)。

注意:因此,默认情况下,绝对定位框的包含块将对应于网格容器的内边距边缘,就像它对块容器所做的那样。

绝对定位发生在网格及其流内内容布局之后,并且不参与任何网格轨道的大小调整,也不以任何方式影响网格的大小/配置。如果网格放置属性通过显式指定此类线或通过跨越现有隐式网格之外来引用不存在的线,则将其视为指定 auto(而不是创建新的隐式网格线)。

注意:请记住,隐式线假定具有所有行名,因此即使未显式命名,引用的线也可能存在。

如果放置仅包含网格跨度,则将其替换为该轴中的两条 auto 线。(当一个轴中的两个网格放置属性最初都贡献了一个跨度,并且§ 8.3.1 网格放置冲突处理导致第二个跨度被忽略时,会发生这种情况。)

10.2. 以网格容器作为父级

网格容器的绝对定位子元素是脱离文档流的,并且不是网格项目,因此不影响其他项目的放置或网格的大小调整。

网格容器的绝对定位子元素的静态位置 [CSS2] 的确定方式,就好像它是网格区域中唯一的网格项目一样,该网格区域的边缘与网格容器的内容边缘重合。

注意:请注意,此位置受子元素上 justify-selfalign-self 值的影响,并且与大多数其他布局模型一样,绝对定位的子元素对其包含块的大小或其内容的布局没有影响。

11. 对齐和间距

网格容器网格轨道确定大小,并且所有网格项目的尺寸最终确定后,网格项目可以在其网格区域内对齐。

注意:子网格网格项目与其父网格的项目一起参与对齐,包括基线对齐;请参阅子网格 (h)

margin 属性可用于以类似于外边距在块布局中的方式对齐项目。网格项目也遵循 CSS Box Alignment Module [CSS-ALIGN-3] 中的盒模型对齐属性,这些属性允许在行和列中轻松地基于关键字对齐项目。

默认情况下,网格项目会拉伸以填充其网格区域。但是,如果 justify-selfalign-self 计算的值不是 stretch,或者外边距是 auto,则网格项目将自动调整大小以适应其内容。

11.1. 间距:row-gapcolumn-gapgap 属性

当在网格容器上指定 row-gapcolumn-gap 属性(及其gap 简写属性)时,它们定义了网格行网格列之间的间距。它们的语法在 CSS Box Alignment 3 § 8 盒间间距中定义。

这些属性的效果就好像受影响的网格线获得了厚度:两条网格线之间的网格轨道是表示它们的间距之间的空间。为了进行轨道大小调整,每个间距都被视为一个额外的、空的、固定大小的轨道,其大小为指定大小,并由跨越其相应网格线的任何网格项目跨越。

注意:由于 justify-content/align-content,可能会在轨道之间添加额外的间距。请参阅 § 12.1 网格大小调整算法。此空间有效地增加了间距的大小。

如果网格在轨道之间分段,则必须抑制这些轨道之间的间距请注意,即使在强制中断之后,间距也会被抑制,这与外边距不同

间距仅出现在隐式网格的轨道之间;第一个轨道之前或最后一个轨道之后没有间距。(特别是,隐式网格的第一个/最后一个轨道与增强网格中的“auto”线之间没有间距。)

折叠轨道的间距折叠时,它们完全重合——两个间距重叠,以便它们的开始和结束边缘重合。如果折叠轨道的一侧没有间距(例如,如果它是隐式网格的第一个或最后一个轨道),那么折叠其间距会导致折叠轨道的任何一“侧”都没有间距。

11.2. 使用 auto 外边距对齐

网格项目上的自动外边距的效果与块布局中的自动外边距非常相似:

11.3. 内联轴对齐:justify-selfjustify-items 属性

网格项目可以通过在网格项目上使用 justify-self 属性或在网格容器上使用 justify-items 属性,在内联维度中对齐,如 [CSS-ALIGN-3] 中所定义。

例如,对于英文文档,内联轴是水平的,因此 justify-* 属性水平对齐网格项目

如果在其在该轴上的大小取决于固有大小的轨道的网格项目上指定了基线对齐(因此其大小取决于项目的大小和基线对齐,从而产生循环依赖),则该项目不参与基线对齐,而是使用其回退对齐,就好像最初指定了该对齐方式一样。为此,当网格容器在相关轴上具有不确定大小时,<flex> 轨道大小计为“固有大小”。

注意:是否使用回退对齐在布局过程中不会改变:如果存在循环,它就存在。

11.4. 块轴对齐:align-selfalign-items 属性

网格项目也可以通过在网格项目上使用 align-self 属性或在网格容器上使用 align-items 属性,在块维度(垂直于内联维度)中对齐,如 [CSS-ALIGN-3] 中所定义。

如果在其在该轴上的大小取决于固有大小的轨道的网格项目上指定了基线对齐(因此其大小取决于项目的大小和基线对齐,从而产生循环依赖),则该项目不参与基线对齐,而是使用其回退对齐,就好像最初指定了该对齐方式一样。为此,当网格容器在相关轴上具有不确定大小时,<flex> 轨道大小计为“固有大小”。

11.5. 对齐网格:justify-contentalign-content 属性

如果网格的外部边缘与网格容器的内容边缘不对应(例如,如果没有列是弹性大小的),则网格轨道将根据网格容器上的 justify-contentalign-content 属性在内容框内对齐。

例如,以下网格垂直居中,并与其网格容器的右边缘对齐:
.grid {
    display: grid;
    grid: 12rem 12rem 12rem 12rem / 10rem 10rem 10rem 10rem;
    justify-content: end;
    align-content: center;
    min-height: 60rem;
}
垂直居中且右对齐的网格示例图

如果没有网格轨道显式网格为空,并且在隐式网格中未创建轨道),则每个轴中的唯一网格线网格容器的起始边缘对齐。

请注意,justify-contentalign-content 的某些值可能导致轨道间隔开(space-aroundspace-betweenspace-evenly)或调整大小(stretch)。如果网格在轨道之间分段,则必须抑制这些轨道之间的任何此类额外间距。

例如,在以下网格中,跨越项目的网格区域会增加以容纳由于对齐而分配给间距的额外空间:
.wrapper {
    display: grid;
    /* 3 行 / 4 列网格容器 */
    grid: repeat(3, auto) / repeat(4, auto);
    gap: 10px;
    align-content: space-around;
    justify-content: space-between;
}

.item1 { grid-column: 1 / 5; }
.item2 { grid-column: 1 / 3; grid-row: 2 / 4; }
.item3 { grid-column: 3 / 5; }
/* 最后两个项目自动放置到最后两个网格单元格中 */
具有 10px 间隙且元素跨越所有列的网格。列的总和小于网格容器的宽度。
对齐前的网格
相同的网格,增加了间隙以吸收多余的网格容器宽度。跨越元素已增长以容纳分配给其跨越的间隙的额外空间。
对齐后的网格

请注意,对齐(与 gap 间距不同)发生在网格轨道确定大小之后,因此如果轨道大小由跨越项目的内容确定,则它将在对齐阶段获得多余的空间以容纳对齐间距。

11.6. 网格容器基线

网格容器的第一(最后)基线确定如下:

  1. 找到网格容器中包含至少一个网格项目的第一(最后)行。

    如果与此行相交的任何网格项目参与该行中的基线对齐,则网格容器的基线集将从这些网格项目的共享对齐基线生成

    否则,网格容器的第一(最后)基线集将从按行优先网格顺序(根据网格容器书写模式)排列的第一个(最后)网格项目对齐基线生成。如果网格项目在网格的内联轴中没有对齐基线,则首先从其边框边缘合成一个。

  2. 如果网格容器不包含任何网格项目,则网格容器没有第一(最后)基线集,如果需要,将根据其对齐上下文的规则合成一个。退出此算法。

网格修改的文档顺序(网格顺序)是在遍历网格的网格单元格时遇到网格项目的顺序。如果同时遇到两个项目,则按顺序修改的文档顺序排列。

当根据上述规则计算基线时,如果贡献基线的框具有允许滚动的 overflow 值,则为了确定其基线,必须将该框视为处于其初始滚动位置。

确定表格单元格的基线时,网格容器提供的基线与行框或表格行提供的基线相同。[CSS2]

有关基线的更多信息,请参阅 CSS Writing Modes 3 § 4.1 基线简介CSS Box Alignment 3 § 9 基线对齐详细信息

12. 网格布局算法

本节定义了网格布局算法,该算法确定网格容器的大小,确定并定位所有网格轨道的大小和位置,并布局已放置到其网格区域中的网格项目

  1. 运行网格项目放置算法以解析网格中所有网格项目(包括子网格及其子项目)的放置。

  2. 根据§ 5.2 网格容器大小调整确定网格容器的大小。

    注意:在此阶段,轨道大小中的循环<percentage>被视为auto

  3. 给定生成的网格容器大小,运行网格大小调整算法以确定网格的大小。

    注意:在此阶段,轨道大小中的<percentage>将根据网格容器大小进行解析。

  4. 网格项目布局到其各自的包含块中。为此,每个网格区域的宽度和高度均被视为确定的

    注意:由于仅使用确定大小计算的公式(例如拉伸适应公式)也是确定的,因此拉伸的网格项目的大小也被视为确定的。

12.1. 网格大小调整算法

本节定义了网格大小调整算法,该算法确定所有网格轨道的大小,并由此确定整个网格的大小。

每个轨道都有指定的最小最大大小调整函数(可能相同)。每个大小调整函数是以下之一:

网格大小调整算法定义了如何将这些大小调整约束解析为使用的轨道大小。

  1. 首先,使用轨道大小调整算法来解析网格列的大小。

    在此过程中,任何在网格容器内联轴中进行子网格划分的网格项目都将被视为空,并且其网格项目(孙项目)将被视为网格容器(其祖父容器)的直接子项。这种内省是递归的。

    仅在块轴中进行子网格划分,并且其网格容器内联轴中的大小取决于其内容大小的项目也会被内省:由于项目在此维度中的大小可能取决于其在另一个维度中子网格化轨道的大小调整,因此任何此类项目对此网格列大小调整的贡献(请参阅解析固有轨道大小)都是在已确定其轨道大小调整仅达到与此本身相同的网格大小调整算法点的前提下进行的。例如,对于此步骤的第一次遍历,项目将仅通过此第一步确定其轨道大小;如果触发此步骤的第二次遍历,则项目将在返回其大小以供此网格列大小调整考虑之前,完成步骤 1-3 的第一次遍历以及此步骤的第二次遍历。同样,这种内省是递归的。

    如果在此步骤中计算网格项目的布局取决于块轴中的可用空间,则假定可用空间是如果任何具有确定最大轨道大小调整函数的行具有该大小并且所有其他行都是无限的时它将具有的空间。如果网格容器和所有轨道都具有确定大小,则还应用 align-content 来查找由此类项目跨越的任何间隙的最终有效大小;否则在此估算中忽略轨道对齐的影响。

  2. 接下来,轨道大小调整算法解析网格行的大小。

    在此过程中,任何在网格容器块轴中进行子网格划分的网格项目都将被视为空,并且其网格项目(孙项目)将被视为网格容器(其祖父容器)的直接子项。这种内省是递归的。

    与调整列大小一样,仅在内联轴中进行子网格划分,并且其网格容器块轴中的大小取决于其内容大小的项目也会被内省。(与调整列大小一样,对此网格行大小调整的贡献是在已确定其轨道大小调整仅达到算法中此对应点的前提下进行的;同样,这种内省是递归的。)

    要查找其块轴大小贡献需要它的任何项目的内联轴可用空间,请使用上一步中计算的网格列大小。如果网格容器内联大小确定的,则还应用 justify-content 来考虑有效的列间隙大小。

  3. 然后,如果任何网格项目的最小内容贡献根据步骤 2 中计算的行大小和对齐方式发生了更改,则使用新的最小内容最大内容贡献重新解析网格列的大小(仅一次)。

    要查找其内联轴大小贡献需要它的任何项目的块轴可用空间,请使用上一步中计算的网格行大小。如果网格容器块大小确定的,则还应用 align-content 来考虑有效的行间隙大小。

    网格项目内联大小取决于其网格区域块大小时,此重复是必要的。示例包括换行的列弹性容器flex-flow: column wrap)、正交流writing-mode)、多列容器以及具有纵横比(或具有具有纵横比的子项)且其大小取决于行大小的项目。
  4. 接下来,如果任何网格项目的最小内容贡献根据步骤 3 中计算的列大小和对齐方式发生了更改,则使用新的最小内容最大内容贡献重新解析网格行的大小(仅一次)。

    要查找其块轴大小贡献需要它的任何项目的内联轴可用空间,请使用上一步中计算的网格列大小。如果网格容器内联大小确定的,则还应用 justify-content 来考虑有效的列间隙大小。

  5. 最后,根据 align-contentjustify-content 属性在网格容器内对齐轨道。

    注意:这可能会在轨道之间引入额外的空间,从而可能扩大跨越间隙的任何网格项目的网格区域,使其超出轨道大小调整期间分配的空间。

注意:子网格化维度中的轨道大小调整将该轴中给定轨道中的每个项目视为父网格的成员。这种交错要求网格大小调整按轴深入到子网格中,而不是在递归时完成两个轴。请注意,这意味着建立正交流子网格的轨道大小调整顺序将与嵌套网格相反。

以下示例说明了如何调整按轴子网格的大小:

假设我们有一个父网格容器 A,它包含一个项目 B,该项目具有子网格化的列,并且包含一个孙项目 C,该孙项目具有子网格化的行,以及一个孙项目 D,它只是一个嵌套网格。

<grid-A>
    <grid-B subgrid=columns>
    <grid-C subgrid=rows></grid-C>
    <grid-D></grid-D>
    </grid-B>
</grid-A>

A 调整其列大小时,它将 B 的项目视为已插入到 A 的相应列中,但是当 A 调整其行大小时,它将 B 视为单个项目(一个具有其自己的行和一些项目(包括项目 CD)的网格容器)。类似地,当 B 调整其行大小时,它将 C 的项目视为已插入到 B 的行中,但是当 B 调整其列大小时,它将 C 视为单个项目,就像处理 D 一样。 C 的行与 A 的行之间没有关系,因为 B 中的行是嵌套的,而不是子网格化的。

从高层次来看,网格算法是:

  1. 调整列的大小
  2. 调整行的大小
  3. 调整列(如果需要,基于最终行大小)

因此,此示例中的网格大小调整算法如下所示:

  1. 解析 A 的网格列的大小,使用 A 的网格项目的大小,将 B 视为空,但将其子项(包括 CD)视为网格 A 中的项目。

    网格算法只是递归到 D 中。对于 C,情况更复杂:

    1. 调整 C 的列的大小。
    2. 通过调整 B 的行的大小来调整 C 的行的大小。
    3. 调整 C 的列。
    4. 返回 C 的最终列大小。

    B 的行的正确大小需要 C 的最终列大小,因为行大小取决于列大小,因此 B 的行很可能取决于 C 的最终列大小。为了打破这种循环依赖关系,我们需要拆分算法以依赖于 C 最终列大小的初始近似值,并在以后进行调整传递。因此,对于 C,我们只需要递归到列大小调整中,并将该初始大小传递给 A 以进行其初始列大小调整。

    稍后当我们调整 B 的行的大小时,我们将调整 C 的行的大小(它们是子网格化的),并通过最终确定其列来完成 C 的大小调整。如果这导致了更改,我们有机会在其调整传递期间触发对 A 列的调整传递。

  2. 接下来,解析 A 的行的大小,使用 A 的网格项目的大小,将 B 视为单个项目。

    由于 B(作为子网格)的大小调整被拆分为多个传递,因此网格算法仅向 B 发出按行大小调整的递归:调整 B 的行的大小,将 D 视为单个项目,请求其最终大小,并将 C 视为空项目并将其子项提升为网格 B 中的项目。

    B 返回其最终行大小,该大小计入 A 的行大小调整传递中。

  3. 最后,最终确定 A 的列大小。如果由于通过 B 的行大小调整传递而导致 C 的最终大小发生更改,则这应触发对 B 列的大小调整,这应触发对 A 列的大小调整传递。

12.2. 轨道尺寸调整术语

最小轨道尺寸调整函数
如果轨道使用 minmax() 函数确定尺寸,则这是该函数的第一个参数。如果轨道使用 <flex> 值或 fit-content() 函数确定尺寸,则为 auto。否则,为轨道的尺寸调整函数。
最大轨道尺寸调整函数
如果轨道使用 minmax() 函数确定尺寸,则这是该函数的第二个参数。否则,为轨道的尺寸调整函数。在所有情况下,将 autofit-content() 视为 max-content,除非对 fit-content() 另有规定。
可用网格空间
在每个维度上独立地,可用网格空间是:

注意:指示基于内容的尺寸调整的 auto 尺寸(例如,水平书写模式中块级框的高度)等同于 max-content

在所有情况下,如果网格容器的 min/max-width/height 属性是确定的,则根据这些属性限制可用网格空间

可用空间
等于可用网格空间减去所有网格轨道(包括间距)的基本尺寸之和,向下取整为零。如果可用网格空间不确定的,则可用空间也是不确定的
跨度计数
网格项目在适用维度中跨越的网格轨道的数量。

注意:请记住,就网格尺寸调整算法而言,间距被视为空的固定尺寸轨道——其最小和最大尺寸调整函数都设置为间距的已用尺寸的轨道。它们的宽度需要相应地并入轨道尺寸调整算法的计算中。

12.3. 轨道尺寸调整算法

本节的其余部分是轨道尺寸调整算法,它根据最小最大轨道尺寸调整函数计算已用轨道尺寸。每个轨道都有一个基本尺寸,一个在整个算法过程中增长并将最终成为轨道最终尺寸的<length>,以及一个增长限制,一个为基本尺寸提供期望最大尺寸的<length>。有 5 个步骤:

  1. 初始化轨道尺寸
  2. 解析固有轨道尺寸
  3. 最大化轨道
  4. 扩展弹性轨道
  5. 扩展拉伸的 auto 轨道

12.4. 初始化轨道尺寸

初始化每个轨道的基本尺寸和增长限制。对于每个轨道,如果轨道的最小轨道尺寸调整函数是:

一个固定尺寸调整函数
解析为一个绝对长度,并使用该尺寸作为轨道的初始基本尺寸

注意:不确定长度不会出现,因为它们被视为 auto

一个固有尺寸调整函数
使用零作为初始基本尺寸

对于每个轨道,如果轨道的最大轨道尺寸调整函数是:

一个固定尺寸调整函数
解析为一个绝对长度,并使用该尺寸作为轨道的初始增长限制
一个固有尺寸调整函数
一个弹性尺寸调整函数
使用无穷大作为初始增长限制

在所有情况下,如果增长限制小于基本尺寸,则将增长限制增加到与基本尺寸匹配。

注意:轨道尺寸调整算法而言,间距被视为空的固定尺寸轨道。

12.5. 解析固有轨道尺寸

此步骤将固有轨道尺寸调整函数解析为绝对长度。首先,它根据完全包含在单个轨道内的项目解析这些尺寸。然后,它逐渐增加跨越多个轨道的项目的空间需求,尽可能均匀地将额外空间分配到这些轨道上。

注意:此步骤完成后,所有固有的基本尺寸增长限制都将解析为绝对长度。

注意:请记住fit-content()auto 最大轨道尺寸调整函数的处理方式与 max-content 相同,除非另有明确规定。

  1. 调整基线对齐的项目,使其固有尺寸贡献反映其基线对齐。对于每个基线共享组中的项目,在每个项目的开始/结束侧(对于第一/最后基线对齐)添加一个“垫片”(实际上是额外的外边距),以便当它们一起开始/结束对齐时,它们的基线按指定方式对齐

    在下面的轨道尺寸调整中,将这些“垫片”视为项目固有尺寸贡献的一部分。如果一个项目使用多个固有尺寸贡献,则它可以为每个贡献设置不同的垫片。

    例如,当网格容器具有不确定大小时,首先在最小/最大内容约束下对其进行布局以找到大小,然后使用该大小“真正地”进行布局(这会影响百分比轨道等)。为每个阶段添加的“垫片”是独立的,并且仅影响该阶段的布局。

    注意:请注意,在此步骤中会同时考虑基线自身对齐基线内容对齐的项目。

    注意:由于其自身大小取决于固有尺寸轨道大小的网格项目不参与基线对齐,因此不会对其进行调整。

  2. 调整轨道尺寸以适应非跨越项目:对于每个具有固有轨道尺寸调整函数且不是弹性尺寸调整函数的轨道,考虑其中跨度为 1 的项目:
    对于最小内容最小值:
    如果轨道具有 min-content 最小轨道尺寸调整函数,则将其基本尺寸设置为项目的最小内容贡献的最大值,向下取整为零。
    对于最大内容最小值:
    如果轨道具有 max-content 最小轨道尺寸调整函数,则将其基本尺寸设置为项目的最大内容贡献的最大值,向下取整为零。
    对于自动最小值:
    如果轨道具有 auto 最小轨道尺寸调整函数,并且网格容器正在最小/最大内容约束下确定大小,则将轨道的基本尺寸设置为其项目的受限最小内容贡献的最大值,向下取整为零。项目的受限最小/最大内容贡献(为此目的)是其最小/最大内容贡献(相应地),受最大轨道尺寸调整函数(可能是fit-content() 轨道尺寸调整函数的参数)的限制(如果该函数是固定的),并最终受其最小贡献(定义如下)的限制。

    否则,将轨道的基本尺寸设置为其项目的最小贡献的最大值,向下取整为零。项目的最小贡献是它可以具有的最小外部尺寸。具体来说,如果项目的计算首选尺寸表现为 auto 或取决于其在相关轴上的包含块的大小,则其最小贡献是假设项目的已用最小尺寸作为其首选尺寸而产生的外部尺寸;否则,项目的最小贡献是其最小内容贡献。因为最小贡献通常取决于项目内容的大小,所以它被认为是固有尺寸贡献的一种类型。

    注意:对于指定最小尺寸为 auto(初始值)的项目,最小贡献通常等同于最小内容贡献——但在某些情况下可能不同,请参阅§ 6.6 网格项目的自动最小尺寸。此外,最小贡献最小内容贡献最大内容贡献

    对于最小内容最大值:
    如果轨道具有 min-content 最大轨道尺寸调整函数,则将其增长限制设置为项目的最小内容贡献的最大值。
    对于最大内容最大值:
    如果轨道具有 max-content 最大轨道尺寸调整函数,则将其增长限制设置为项目的最大内容贡献的最大值。对于 fit-content() 最大值,进一步通过 fit-content() 参数限制此增长限制

    在所有情况下,如果轨道的增长限制现在小于其基本尺寸,则将增长限制增加到与基本尺寸匹配。

    注意:此步骤是下面处理跨越项目的步骤的简化,并且应产生与在跨度为 1 的项目上运行这些指令相同的行为。

  3. 增加尺寸以容纳跨越内容尺寸轨道的跨越项目:接下来,考虑跨度为 2 且不跨越具有弹性尺寸调整函数的轨道的项目。
    1. 对于固有最小值:首先将额外空间分配给具有固有最小轨道尺寸调整函数的轨道的基本尺寸,以容纳这些项目的最小贡献

      如果网格容器正在最小最大内容约束下确定大小,则在此处使用项目的受限最小内容贡献代替其最小贡献。(对于跨越多个轨道的项目,用于计算其受限最小/最大内容贡献的上限是其跨越的任何轨道的固定最大轨道尺寸调整函数总和,并且如果它仅跨越此类轨道,则应用该上限。)

    2. 对于基于内容的最小值:接下来继续将额外空间分配给具有最小轨道尺寸调整函数min-contentmax-content 的轨道的基本尺寸,以容纳这些项目的最小内容贡献
    3. 对于最大内容最小值:接下来,如果网格容器正在最大内容约束下确定大小,则继续将额外空间分配给具有最小轨道尺寸调整函数automax-content 的轨道的基本尺寸,以容纳这些项目的受限最大内容贡献

      在所有情况下,继续将额外空间分配给具有最小轨道尺寸调整函数max-content 的轨道的基本尺寸,以容纳这些项目的最大内容贡献

    4. 如果此时任何轨道的增长限制现在小于其基本尺寸,则将其增长限制增加到与其基本尺寸匹配。
    5. 对于固有最大值:接下来将额外空间分配给具有固有最大轨道尺寸调整函数的轨道的增长限制,以容纳这些项目的最小内容贡献。将在此步骤中增长限制从无限变为有限的任何轨道标记为下一步的无限可增长
      为什么存在无限可增长标志?

      Peter Salas 解释道

      考虑以下情况:
      
      两个“auto”轨道(即“minmax(min-content, max-content) minmax(min-content, max-content)”)。
      项目 1 在轨道 1 中,并且 min-content = max-content = 10。
      项目 2 跨越轨道 1 和 2,并且 min-content = 30,max-content = 100。
      
      在解析第一个项目的 min-content/max-content 后,我们得到:
      
      轨道 1:基本尺寸 = 10 增长限制 = 10
      
      轨道 2:基本尺寸 = 0 增长限制 = 无限
      
      然后我们解析第二个项目的 min-content/max-content。
      
      阶段 1 将轨道 2 的基本尺寸设置为 20,以便两个轨道的基本尺寸之和为 30。
      阶段 2 不执行任何操作,因为没有相关的轨道。
      阶段 3 将轨道 2 的增长限制设置为 20,以便两个轨道的增长限制之和为 30。
      在阶段 4 中,我们需要将增长限制之和增加 70 以容纳项目 2。
      有两种选择:
      
      1. 平均增加每个轨道的增长限制,最终得到增长限制 = [45, 55]。
      2. 仅增加第二个轨道的增长限制,最终得到增长限制 = [10, 90]。
      
      通过在空间分配期间不将刚设置的增长限制视为约束(即将其视为无限),我们得到了第二个结果,我们认为这是一个更好的结果,因为第一个轨道的大小仍然完全适合第一个项目。
      
    6. 对于最大内容最大值:最后继续将额外空间分配给具有最大轨道尺寸调整函数max-content 的轨道的增长限制,以容纳这些项目的最大内容贡献

    对于具有更大跨度的项目,逐步重复,直到考虑了所有项目。

  4. 增加尺寸以容纳跨越弹性轨道的跨越项目:接下来,重复上一步,改为(一起,而不是按跨度大小分组)考虑所有确实跨越具有弹性尺寸调整函数的轨道的项目,同时
    • 将空间分配给弹性轨道(即将所有其他轨道视为具有固定尺寸调整函数
    • 如果项目跨越的所有弹性轨道弹性尺寸调整函数之和大于或等于 1,则根据其弹性尺寸调整函数的比例将空间分配给此类轨道,而不是平均分配空间;如果总和小于 1,则根据其弹性尺寸调整函数的比例分配该比例的空间,其余部分平均分配
  5. 如果任何轨道仍然具有无限的增长限制(例如,因为它没有放置任何项目,或者它是一个弹性轨道),则将其增长限制设置为其基本尺寸

注意:当项目跨越多个轨道时,没有单一的方法可以满足固有尺寸约束。此算法体现了许多启发式方法,这些方法已被证明在实际用例中(例如本规范前面的“游戏”示例)可以提供良好的结果。将来可能会更新此算法,以考虑已识别的更高级的启发式方法。

12.5.1. 在跨越轨道间分配额外空间

分配额外空间,请执行以下步骤,并使用以下输入:
  1. 为每个受影响轨道单独维护一个计划增量,初始设置为 0。(这可以防止尺寸增加变得与顺序相关。)
  2. 对于每个容纳的项目,仅考虑该项目跨越的轨道:
    1. 找到要分配的空间:从项目的尺寸贡献中减去每个跨越轨道(不仅仅是受影响轨道)的受影响尺寸,向下取整为零。(对于无限的增长限制,替换为轨道的基本尺寸。)这个剩余的尺寸贡献就是要分配的空间
      空间 = max(0, 尺寸贡献 - ∑轨道尺寸)
    2. 空间分配至限制:

      通过以下方式找到每个受影响轨道项目引发的增量:在这些轨道之间平均分配空间,当轨道的受影响尺寸 + 项目引发的增量达到其限制时,冻结该轨道的项目引发的增量(并根据需要继续增长未冻结的轨道)。

      对于基本尺寸限制是其增长限制,如果存在fit-content()参数,则受其限制。对于增长限制,如果增长限制是有限的并且轨道不是无限可增长的,则限制增长限制,否则,如果它具有fit-content() 轨道尺寸调整函数,则为其fit-content()参数,否则为无穷大。

      注意:如果受影响尺寸增长限制并且轨道未标记为无限可增长的,则每个项目引发的增量将为零。

    3. 空间分配给非受影响轨道:

      如果此时仍有额外的空间,并且项目同时跨越受影响轨道和非受影响轨道,则按照上一步的方式分配空间,但分配给非受影响轨道

      注意:这将任何剩余空间分配到尚未达到其增长限制的轨道中,而不是违反受影响轨道的增长限制。

    4. 空间分配超出限制:

      如果此时仍有额外的空间,则解冻并继续将空间分配给……的项目引发的增量

      为此目的,fit-content()轨道的最大轨道尺寸调整函数被视为max-content,直到轨道达到指定为fit-content()参数的限制,之后其最大轨道尺寸调整函数被视为该参数的固定尺寸调整函数(这可以更改在此步骤中继续接收空间的轨道)。

      注意:此步骤根据其最大轨道尺寸调整函数的类型,优先分配空间以容纳超出轨道当前增长限制的尺寸贡献

    5. 对于每个受影响轨道,如果轨道的项目引发的增量大于轨道的计划增量,则将轨道的计划增量设置为该值。
  3. 更新轨道的受影响尺寸,方法是加上计划增量,以便下一轮空间分配将考虑该增量。(如果受影响尺寸是无限的增长限制,则将其设置为轨道的基本尺寸加上计划增量。)

12.6. 最大化轨道

如果可用空间为正,则将其平均分配给所有轨道的基本尺寸,当轨道达到其增长限制时冻结轨道(并根据需要继续增长未冻结的轨道)。

为此步骤的目的:如果在网格容器最大内容约束下确定大小,则可用空间是无限的;如果在最小内容约束下确定大小,则可用空间为零。

如果这将导致网格大于受其最大宽度/高度限制的网格容器内部尺寸,则重新执行此步骤,将可用网格空间视为等于网格容器在调整为其最大宽度/高度时的内部尺寸

12.7. 扩展弹性轨道

此步骤使用它可以分配给fr的最大值来确定弹性轨道的大小,而不会超过可用空间

首先,找到网格已用的弹性分数

如果可用空间为零,或者如果在网格容器最小内容约束下确定大小:
已用弹性分数为零。
否则,如果可用空间确定的长度:
已用弹性分数是使用所有网格轨道可用网格空间要填充的空间查找 fr 的大小的结果。
否则,如果可用空间不确定的长度:
已用弹性分数是以下各项的最大值:

如果使用此弹性分数会导致网格小于网格容器最小宽度/高度(或大于网格容器最大宽度/高度),则重新执行此步骤,将可用空间视为确定的,并将可用网格空间视为等于网格容器在调整为其最小宽度/高度最大宽度/高度)时的内部尺寸

对于每个弹性轨道,如果已用弹性分数与轨道的弹性因子的乘积大于轨道的基本尺寸,则将其基本尺寸设置为该乘积。

12.7.1. 查找 fr 的大小

此算法查找 fr 单位在不超过目标大小的情况下可以具有的最大大小。必须使用一组网格轨道和一定数量的要填充的空间来调用它。

  1. 剩余空间要填充的空间减去非弹性网格轨道基本尺寸
  2. 弹性因子总和弹性轨道弹性因子之和。如果此值小于 1,则将其设置为 1。
  3. 假设的 fr 大小剩余空间除以弹性因子总和
  4. 如果假设的 fr 大小弹性轨道弹性因子的乘积小于轨道的基本尺寸,则重新启动此算法,将所有此类轨道视为非弹性的。
  5. 返回假设的 fr 大小

12.8. 拉伸 auto 轨道

网格容器内容分布属性在此轴向上为 normalstretch 时,此步骤通过将任何剩余的正确定可用空间平均分配给具有 auto 最大轨道尺寸调整函数的轨道来扩展这些轨道。如果可用空间不确定的,但网格容器具有确定的最小宽度/高度,则改用该尺寸计算此步骤的可用空间

13. 网格布局分片

网格容器可以在行或列之间以及项目内部跨页断开。 break-* 属性像它们参与的格式化上下文中的正常情况一样应用于网格容器。本节定义了它们如何应用于网格项目和网格项目的内容。

以下断行规则将分片容器称为“页面”。相同的规则适用于任何其他分片上下文。(根据需要将“页面”替换为适当的分片容器类型。)请参阅 CSS 分片模块 [CSS3-BREAK]

分片网格容器的确切布局未在此级别的网格布局中定义。但是,网格容器内的断行受以下规则约束:

13.1. 示例分片算法

本节是非规范性的。

这是一种可能的分片算法的粗略草案,仍需要与 [CSS-FLEXBOX-1] 算法进行严格的交叉检查以确保一致性。欢迎提供反馈;请参考上述规则作为实现指南。

  1. 遵循§ 12 网格布局算法,通过使用分片容器的内联大小并假设无限的块大小来布局网格。在此步骤中,必须解析所有grid-row autofr 值。
  2. 使用上一步中解析的值布局网格容器。
  3. 如果网格区域的大小由于分片而发生变化(在此决定中不包括跨行的项目),则根据需要增加以下行的网格行大小:
    • 具有内容最小轨道尺寸调整函数。
    • 位于没有显式高度且网格行为弹性的网格中。
  4. 如果网格高度为 auto,则网格的高度应为最终行大小的总和。
  5. 如果由于分片期间边距折叠导致网格区域溢出网格容器,则扩展网格容器以包含此网格区域(此步骤对于避免由于分片而导致的循环布局依赖性是必要的)。

如果指定了网格的高度,则第三步和第四步可能会导致网格行溢出网格。

14. 隐私注意事项

网格布局未引入新的隐私泄露问题。

15. 安全注意事项

网格布局未引入新的安全注意事项。

16. 变更

16.1. 2020 年 12 月 18 日 CR 以来的变更

16.2. 2020 年 8 月 CR 以来的变更

2019 年 12 月 CSS 网格布局级别 2 工作草案以来的变更

无,除了整合了 CSS 网格级别 1 的全文。

有关先前的变更,请参阅工作草案期间的变更

16.3. 自级别 1 以来的新增内容

级别 1以来已添加以下功能:

17. 致谢

非常感谢 Mozilla 的 Mats Palmgren,没有他的支持和反馈,子网格功能将无法推进。还要感谢 Daniel Tonon,他坚持在子网格中间隙的智能处理,并贡献了插图;以及 Rachel Andrew 和 Jen Simmons,她们帮助弥合了 CSS 工作组与 Web 设计/创作社区之间的反馈差距。

最后,CSS 网格级别 2 的致谢部分若不提及所有使CSS 网格级别 1 这项艰巨任务成为可能的人,那将是不完整的。

一致性

文档约定

一致性要求通过描述性断言和 RFC 2119 术语的组合来表达。本文档规范部分的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”和“OPTIONAL”应按照 RFC 2119 中的描述进行解释。但是,为了便于阅读,这些词在本规范中并非全部大写。

本规范的所有文本都是规范性的,明确标记为非规范性的部分、示例和注释除外。[RFC2119]

本规范中的示例以“例如”一词开头,或使用 class="example" 与规范性文本分开,如下所示:

这是一个信息性示例的例子。

信息性注释以“注意”一词开头,并使用 class="note" 与规范性文本分开,如下所示:

注意,这是一个信息性注释。

建议是规范性部分,其样式旨在引起特别注意,并使用 <strong class="advisement"> 与其他规范性文本分开,如下所示: 用户代理必须提供可访问的替代方案。

一致性类别

本规范的一致性针对三个一致性类别进行定义:

样式表
一个 CSS 样式表
渲染器
一个用户代理,它解释样式表的语义并渲染使用它们的文档。
创作工具
一个用户代理,它编写样式表。

如果样式表中使用本模块中定义的语法的所有语句都根据通用 CSS 语法和本模块中定义的每个功能的各个语法有效,则该样式表符合本规范。

如果渲染器除了按照相应规范的定义解释样式表外,还通过正确解析并相应地渲染文档来支持本规范定义的所有功能,则该渲染器符合本规范。但是,由于设备限制导致用户代理无法正确渲染文档并不会使该用户代理不符合规范。(例如,不要求用户代理在单色监视器上渲染颜色。)

如果创作工具编写的样式表在语法上根据通用 CSS 语法和本模块中每个功能的各个语法是正确的,并且满足本模块中描述的样式表的所有其他一致性要求,则该创作工具符合本规范。

部分实现

为了使作者能够利用向前兼容的解析规则来分配回退值,CSS 渲染器必须将任何它们没有可用支持级别的 at-rules、属性、属性值、关键字和其他语法结构视为无效(并酌情忽略)。特别是,用户代理不得在单个多值属性声明中选择性地忽略不受支持的组件值并支持受支持的值:如果任何值被视为无效(不受支持的值必须如此),CSS 要求忽略整个声明。

不稳定和专有功能的实现

为避免与未来稳定的 CSS 功能发生冲突,CSSWG 建议在实现 CSS 的不稳定功能和专有扩展遵循最佳实践

非实验性实现

一旦规范达到候选推荐阶段,就可以进行非实验性实现,并且实现者应发布他们可以证明已根据规范正确实现的任何 CR 级别功能的无前缀实现。

为了建立和维护 CSS 在不同实现之间的互操作性,CSS 工作组要求非实验性 CSS 渲染器在发布任何 CSS 功能的无前缀实现之前向 W3C 提交一份实现报告(以及必要时用于该实现报告的测试用例)。提交给 W3C 的测试用例将由 CSS 工作组进行审查和更正。

有关提交测试用例和实现报告的更多信息,请访问 CSS 工作组网站 https://www.w3.org/Style/CSS/Test/。问题应发送至 public-css-testsuite@w3.org 邮件列表。

CR 退出标准

为了使本规范能够进入提议推荐阶段,每个功能必须至少有两个独立的、可互操作的实现。每个功能可以由不同的产品集实现,不要求所有功能都由单个产品实现。为此标准的目的,我们定义以下术语:

独立的
每个实现必须由不同的方开发,并且不能共享、重用或派生自另一个合格实现使用的代码。与本规范的实现无关的代码部分不受此要求的约束。
可互操作的
通过官方 CSS 测试套件中的相应测试用例,或者,如果实现不是 Web 浏览器,则通过等效测试。如果使用此类用户代理 (UA) 来声明互操作性,则测试套件中的每个相关测试都应创建一个等效测试。此外,如果使用此类 UA 来声明互操作性,则必须有一个或多个其他 UA 也能够以相同的方式通过这些等效测试以实现互操作性。等效测试必须公开发布以供同行评审。
实现
一个用户代理,它:
  1. 实现了该规范。
  2. 向公众开放。该实现可以是已发布的产品或其他公开发布的版本(即 beta 版、预览版或“每日构建版”)。未发布的产品版本必须已实现该功能至少一个月,以证明其稳定性。
  3. 不是实验性的(即,专门设计用于通过测试套件且不打算在未来正常使用的版本)。

该规范将至少保留候选推荐状态六个月。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性参考文献

[CSS-ALIGN-3]
Elika Etemad; Tab Atkins Jr.. CSS Box Alignment Module Level 3. 2025 年 3 月 11 日. WD. URL: https://www.w3.org/TR/css-align-3/
[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4. 2024 年 8 月 4 日. WD. URL: https://www.w3.org/TR/css-box-4/
[CSS-BREAK-4]
Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 4. 2018 年 12 月 18 日. FPWD. URL: https://www.w3.org/TR/css-break-4/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5. 2022 年 1 月 13 日. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-CONTAIN-2]
Tab Atkins Jr.; Florian Rivoal; Vladimir Levin. CSS Containment Module Level 2. 2022 年 9 月 17 日. WD. URL: https://www.w3.org/TR/css-contain-2/
[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 3. 2023 年 3 月 30 日. CR. URL: https://www.w3.org/TR/css-display-3/
[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 4. 2024 年 12 月 19 日. FPWD. URL: https://www.w3.org/TR/css-display-4/
[CSS-FLEXBOX-1]
Tab Atkins Jr.; 等. CSS Flexible Box Layout Module Level 1. 2018 年 11 月 19 日. CR. URL: https://www.w3.org/TR/css-flexbox-1/
[CSS-GRID-1]
Tab Atkins Jr.; 等. CSS Grid Layout Module Level 1. 2020 年 12 月 18 日. CRD. URL: https://www.w3.org/TR/css-grid-1/
[CSS-IMAGES-3]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS Images Module Level 3. 2023 年 12 月 18 日. CRD. URL: https://www.w3.org/TR/css-images-3/
[CSS-INLINE-3]
Elika Etemad. CSS Inline Layout Module Level 3. 2024 年 12 月 18 日. WD. URL: https://www.w3.org/TR/css-inline-3/
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal. CSS Overflow Module Level 3. 2023 年 3 月 29 日. WD. URL: https://www.w3.org/TR/css-overflow-3/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.. CSS Positioned Layout Module Level 3. 2025 年 3 月 11 日. WD. URL: https://www.w3.org/TR/css-position-3/
[CSS-PSEUDO-4]
Daniel Glazman; Elika Etemad; Alan Stearns. CSS Pseudo-Elements Module Level 4. 2022 年 12 月 30 日. WD. URL: https://www.w3.org/TR/css-pseudo-4/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad. CSS Box Sizing Module Level 3. 2021 年 12 月 17 日. WD. URL: https://www.w3.org/TR/css-sizing-3/
[CSS-SIZING-4]
Tab Atkins Jr.; Elika Etemad; Jen Simmons. CSS Box Sizing Module Level 4. 2021 年 5 月 20 日. WD. URL: https://www.w3.org/TR/css-sizing-4/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 2021 年 12 月 24 日. CRD. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-TEXT-4]
Elika Etemad; 等. CSS Text Module Level 4. 2024 年 5 月 29 日. WD. URL: https://www.w3.org/TR/css-text-4/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. 2024 年 3 月 22 日. CRD. URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 2024 年 3 月 12 日. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii. CSS Writing Modes Level 4. 2019 年 7 月 30 日. CR. URL: https://www.w3.org/TR/css-writing-modes-4/
[CSS2]
Bert Bos; 等. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 2011 年 6 月 7 日. REC. URL: https://www.w3.org/TR/CSS2/
[CSS3-BREAK]
Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 3. 2018 年 12 月 4 日. CR. URL: https://www.w3.org/TR/css-break-3/
[CSS3-WRITING-MODES]
Elika Etemad; Koji Ishii. CSS Writing Modes Level 3. 2019 年 12 月 10 日. REC. URL: https://www.w3.org/TR/css-writing-modes-3/
[CSSOM]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021 年 8 月 26 日. WD. URL: https://www.w3.org/TR/cssom-1/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[MEDIAQUERIES-5]
Dean Jackson; 等. Media Queries Level 5. 2021 年 12 月 18 日. WD. URL: https://www.w3.org/TR/mediaqueries-5/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997 年 3 月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEB-ANIMATIONS-1]
Brian Birtles; 等. Web Animations. 2023 年 6 月 5 日. WD. URL: https://www.w3.org/TR/web-animations-1/

信息性参考文献

[CSS-MULTICOL-2]
Florian Rivoal; Rachel Andrew. CSS Multi-column Layout Module Level 2. 2024 年 12 月 19 日. FPWD. URL: https://www.w3.org/TR/css-multicol-2/
[HTML]
Anne van Kesteren; 等. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/

属性索引

名称 初始值 适用于 继承性 百分比 动画类型 规范顺序 计算值
grid <'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'> none 网格容器 见单个属性 见单个属性 见单个属性 per grammar 见单个属性
grid-area <grid-line> [ / <grid-line> ]{0,3} auto 网格项和其包含块是网格容器的绝对定位框 N/A 离散 per grammar 见单个属性
grid-auto-columns <track-size>+ auto 网格容器 见轨道尺寸调整 如果列表长度匹配,则按每项的计算值类型;否则为离散 per grammar 见轨道尺寸调整
grid-auto-flow [ row | column ] || dense row 网格容器 n/a 离散 per grammar 指定的关键字
grid-auto-rows <track-size>+ auto 网格容器 见轨道尺寸调整 如果列表长度匹配,则按每项的计算值类型;否则为离散 per grammar 见轨道尺寸调整
grid-column <grid-line> [ / <grid-line> ]? auto 网格项和其包含块是网格容器的绝对定位框 N/A 离散 per grammar 见单个属性
grid-column-end <grid-line> auto 网格项和其包含块是网格容器的绝对定位框 n/a 离散 per grammar 指定的关键字、标识符和/或整数
grid-column-start <grid-line> auto 网格项和其包含块是网格容器的绝对定位框 n/a 离散 per grammar 指定的关键字、标识符和/或整数
grid-row <grid-line> [ / <grid-line> ]? auto 网格项和其包含块是网格容器的绝对定位框 N/A 离散 per grammar 见单个属性
grid-row-end <grid-line> auto 网格项和其包含块是网格容器的绝对定位框 n/a 离散 per grammar 指定的关键字、标识符和/或整数
grid-row-start <grid-line> auto 网格项和其包含块是网格容器的绝对定位框 n/a 离散 per grammar 指定的关键字、标识符和/或整数
grid-template none | [ <'grid-template-rows'> / <'grid-template-columns'> ] | [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]? none 网格容器 见单个属性 见单个属性 见单个属性 per grammar 见单个属性
grid-template-areas none | <string>+ none 网格容器 n/a 离散 per grammar 关键字 none 或字符串值列表
grid-template-columns none | <track-list> | <auto-track-list> | subgrid <line-name-list>? none 网格容器 参照内容区域的相应维度 如果列表长度匹配,则按计算轨道列表中每项的计算值类型(参见和);否则为离散 per grammar 关键字 none 或计算轨道列表
grid-template-rows none | <track-list> | <auto-track-list> | subgrid <line-name-list>? none 网格容器 参照内容区域的相应维度 如果列表长度匹配,则按计算轨道列表中每项的计算值类型(参见和);否则为离散 per grammar 关键字 none 或计算轨道列表

问题索引

如果您注意到此网格布局模块与弹性框布局模块之间存在任何不一致之处,请向 CSSWG 报告,因为这很可能是一个错误。
上述列表的第一点意味着隐式轨道作为 grid-template-rows 等的一部分进行序列化,尽管作者实际上无法在这些属性中指定隐式轨道大小!因此 grid-template-rowsgrid-template-columns 值可能无法正确往返:
const s = getComputedStyle(gridEl);
gridEl.style.gridTemplateRows = s.gridTemplateRows;
// 这样的代码 应该 是一个无操作,
// 但是如果存在任何隐式行,
// 这会将其转换为显式行,
// 可能会改变网格项的定位方式
// 并改变网格的整体大小!

这是一个早期实现的意外属性,在没有经过深思熟虑的情况下泄漏到后来的实现中。我们打算从规范中删除它,但要等到我们为获取有关隐式轨道的信息定义了 CSSOM API 之后,因为目前这是获取该信息的唯一方法,并且许多页面都依赖于此。

CSS 工作组正在考虑是否也为网格放置属性返回使用值,并正在寻求反馈,尤其是来自实现者的反馈。参见讨论