CSS探索系列之grid布局

网格布局(CSS Grid Layout) 把容器划成行和列交叉的格子,项目按网格线或命名区域落到二维平面上的任意一块。Flex 一次只排一根轴;Grid 同时管两根轴,页面骨架、卡片墙、不规则拼贴都从这里下手。

基本示例

<div class="wrapper">
  <div class="item one">One</div>
  <div class="item two">Two</div>
  <div class="item three">Three</div>
  <div class="item four">Four</div>
  <div class="item five">Five</div>
  <div class="item six">Six</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  grid-auto-rows: minmax(100px, auto);
}
.item {
  border: 2px solid rgb(233, 171, 88);
  border-radius: 5px;
  background-color: rgba(233, 171, 88, 0.5);
  padding: 1em;
  color: #d9480f;
}
/* .one 与 .two 在 (列2, 行1) 重叠:Grid 允许项目占同一区域 */
.one {
  grid-column: 1 / 3;
  grid-row: 1;
}
.two {
  grid-column: 2 / 4;
  grid-row: 1 / 3;
}
.three {
  grid-row: 2 / 5;
  grid-column: 1;
}
.four {
  grid-column: 3;
  grid-row: 3;
}
.five {
  grid-column: 2;
  grid-row: 4;
}
.six {
  grid-column: 3;
  grid-row: 4;
}

image-20260729171105918

基础术语

  • 网格(Grid):一组相交的水平线和垂直线,划出列和行。
  • 网格线(Grid line):分割轨道的竖线、横线。可以从 1 起用数字引用,也可以起名字。
  • 网格轨道(Grid track):两条相邻网格线之间的一条带,不是行就是列。
  • 网格行(Grid row):水平轨道。
  • 网格列(Grid column):垂直轨道。
  • 网格单元格(Grid cell):四条线围成的最小格子。
  • 网格区域(Grid area):一个或多个单元格拼成的矩形。
  • 网格间隙(Gutter):轨道与轨道之间的间距,由 gap 控制。
  • 网格轴:行轴是行内方向(水平书写时左右),对齐属性带 justify-;列轴是块方向(水平书写时上下),对齐属性带 align-

display 属性

display: grid 生成块级网格容器,display: inline-grid 生成行内级网格容器。两者内部排版规则相同,差别只在容器自己在文档流里占一块还是挤在一行里。

它们会建立网格格式化上下文(Grid Formatting Context,GFC),不是 BFC。容器的每个子元素都是网格项(含 ::before::after)。文本节点会生成匿名网格项。绝对定位的子元素不参与网格排版。

备注floatclearvertical-align 对网格项无效。

注意: 现行 Grid 语法与 IE11 的 -ms-grid 不是同一套。下文「常用值」指已支持现行 Grid 的浏览器里可放心用的取值;「其余取值」仍有缺口。

容器属性

  1. grid-template-columnsgrid-template-rowsgrid-template-areasgrid-template
  2. grid-auto-columnsgrid-auto-rowsgrid-auto-flow
  3. grid
  4. gaprow-gapcolumn-gap
  5. justify-itemsalign-itemsplace-items
  6. justify-contentalign-contentplace-content

grid-template-columns

定义垂直网格线的名称,以及显式列轨道的尺寸。

初始值:none(列数和列宽交给 grid-auto-columns 在隐式网格里补)。

grid-template-columns: [线名] 轨道尺寸 [线名] 轨道尺寸 ...;

常用值:

  • 长度:pxremem 等,列宽不随内容或容器伸缩。
  • 百分比:相对网格容器内容区宽度。容器宽度自己还在靠内容撑开(例如未设宽的 inline-grid)时,百分比按 auto 处理。
  • fr:弹性系数,分的是扣掉固定轨道和 gap 之后的剩余空间
  • auto:先按内容估尺寸。没有 fr 轨道时,剩余空间还可以被 justify-content: stretch 拉长;和 fr 共存时,内容定宽之后剩下的才给 fr,不是先分光 fr 再把余量给 auto
  • minmax(min, max):列宽夹在上下限之间。min 不能是 fr
  • repeat():重复一段轨道定义。第一个参数可以是次数,也可以是 auto-fillauto-fit

其余取值(存在浏览器兼容限制):

  • min-content:按内容最小宽度(中文通常落到最宽的那个字)。
  • max-content:按内容最大自然宽度(最宽的那一格撑开)。
  • fit-content(<length-percentage>):须写成函数,如 fit-content(200px),相当于 min(max-content, max(min-content, 指定长度)),列宽尽量贴近内容,但不超过指定长度。
/* 不带命名:3 条列轨道,4 根垂直网格线(数字线号 1、2、3、4 是隐式的) */
grid-template-columns: 100px 1fr 200px;

/* 显式命名(自定义线名不能以数字开头) */
grid-template-columns: [start] 100px [center-start] 1fr [center-end] 200px [end];

/* 一条线可以有多个名字,空格分隔 */
grid-template-columns: [left sidebar-start] 240px [sidebar-end main-start] 1fr [main-end];

/* repeat 里的名字会按次数复制:
1 号线:col-start
2 号线:col-end col-start
3 号线:col-end col-start
4 号线:col-end
col-start 2 → 第 2 条名叫 col-start 的线
*/
grid-template-columns: repeat(3, [col-start] 1fr [col-end]);

grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

注意:

  • 1fr 实际按 minmax(auto, 1fr) 处理,下限仍是内容尺寸。列里有长单词或不换行文本时,轨道收不下去,会出现横向溢出。要允许收到内容之下,写成 minmax(0, 1fr)
  • 百分比相对容器总宽,fr 相对剩余宽;两者混用时先结算百分比和固定尺寸,再分 fr
  • auto-fill:能放下多少条轨道就放多少,空轨道仍占位。
  • auto-fit:同样尽量多放,但会把空轨道收成 0,让已有轨道去填容器。

grid-template-rows

定义水平网格线名称与显式行轨道尺寸。初始值、语法、轨道函数、线名规则与 grid-template-columns 相同,只是作用在行上。

grid-template-areas

命名区域画出整张网格。每个字符串是一行,字符串里空格分开的单词是一列;每一行的列数必须相同,否则整条声明无效。. 表示空格。同一名字会合并成一块区域,这块必须是矩形。

.grid {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: 80px 1fr 60px;
  grid-template-areas:
    "header header header"
    "sidebar main aside"
    "footer footer footer";
}

注意: 区域图给出的列数应与 grid-template-columns 一致;对不上时,grid-template-areas 被忽略。没有写 grid-template-rows 时,区域会按行数长出隐式行,高度由内容决定。

grid-template

grid-template-rowsgrid-template-columnsgrid-template-areas 的简写。

grid-template: <grid-template-rows> / <grid-template-columns>;
grid-template: <grid-template-areas> <grid-template-rows> / <grid-template-columns>;
grid-template: 100px 200px / 1fr 2fr 1fr;

/* 等价于 */
grid-template-rows: 100px 200px;
grid-template-columns: 1fr 2fr 1fr;
grid-template-areas: none;
grid-template:
  "header header header" 80px
  "sidebar main aside" 1fr
  "footer footer footer" 60px
  / 200px 1fr 200px;

/* 等价于 */
grid-template-rows: 80px 1fr 60px;
grid-template-columns: 200px 1fr 200px;
grid-template-areas:
  "header header header"
  "sidebar main aside"
  "footer footer footer";

grid-auto-columns

指定隐式列的轨道尺寸。初始值:auto。取值与 grid-template-columns 相同。

显式列由 grid-template-columns 画好。网格项落到显式列之外,浏览器才补隐式列,宽度听 grid-auto-columns

.grid {
  display: grid;
  grid-template-columns: 100px 200px; /* 只有 2 列,列线 1→2→3 */
  grid-auto-columns: 150px;
}

.item {
  grid-column: 2 / 5; /* 要到列线 5,自动补出第 3、4 列 */
}

grid-auto-rows

指定隐式行的轨道尺寸。初始值、取值、触发方式和 grid-auto-columns 对称。

grid-auto-flow

控制未指定坐标的网格项怎么自动往格子里填,以及隐式网格往行长还是往列长。

初始值:row

常用值:

  • row:按行填,从左到右、从上到下;不够就加隐式行。
  • column:按列填,从上到下、从左到右;不够就加隐式列。
  • dense:尽量拿后面的项去填前面留下的空洞。单独写 dense 时方向仍是 row
  • row dense:与单独写 dense 相同。
  • column dense:按列做密集填充。

注意: dense 会打乱视觉顺序和 DOM 顺序的对应关系,读屏和 Tab 仍跟源码走。

grid

同时设置显式网格、隐式网格和自动放置,是 grid-template-*grid-auto-*grid-auto-flow 的超集简写。没写到的分量会被重置成初始值。

grid: <grid-template>
grid: <grid-template-rows> / <grid-template-columns>
grid: <grid-template-rows> / auto-flow [dense?] <grid-auto-columns>;
grid: auto-flow [dense?] <grid-auto-rows> / <grid-template-columns>;
grid: 100px 200px / 1fr 2fr;

/* 等价于 */
grid-template-rows: 100px 200px;
grid-template-columns: 1fr 2fr;
grid-template-areas: none;
grid-auto-rows: auto;
grid-auto-columns: auto;
grid-auto-flow: row;
/* auto-flow 写在 / 右侧:grid-auto-flow 为 column */
grid: 100px 200px / auto-flow 1fr;

/* auto-flow 写在 / 左侧:grid-auto-flow 为 row */
grid: auto-flow 1fr / 100px 200px;

注意: / 每一侧只能表达一种定义方式,要么显式,要么隐式,不能同一侧同时写 grid-template-rowsgrid-auto-rows(列同理)。

gap

设置轨道之间的间距,不作用到容器内边缘。gap 不计入 fr 的「剩余空间」分母之外的固定部分,算 fr 之前会先扣掉。

row-gap: 16px;      /* 行与行(纵向) */
column-gap: 12px;   /* 列与列(横向) */
gap: 16px;          /* 行列同一间距 */
gap: 16px 12px;     /* row-gap column-gap */

grid-row-gapgrid-column-gapgrid-gap 是早期名字,现在是 row-gapcolumn-gapgap 的别名。新代码用后者。

属性浏览器兼容: 弹性容器上的 gapFlex 篇;网格容器上,现行 Grid 浏览器都支持。IE11 的旧 Grid 不支持。

网格里的对齐分两层:项目在各自格子里*-items*-self),以及整张轨道在容器里*-content)。

justify-items

网格项在格子内沿行轴对齐。水平书写时就是水平对齐。

初始值:normal。在网格里表现与 stretch 相同。有固有宽高比的替换元素(如图片)不会被拉变形,按 start 处理。

常用值:

  • stretch:拉满格子的行轴尺寸。
  • start:靠行轴起点。
  • end:靠行轴终点。
  • center:行轴居中。

其余取值(存在浏览器兼容限制):

  • leftright:物理左、右。所处轴向不与行内轴平行时,按 start 处理。
  • self-startself-end:跟项目自身书写方向对齐,可以和容器的 startend 不一致。
  • flex-startflex-end:在 Grid 里分别等同于 startend,为兼容 Flex 写法而保留。
  • safeunsafe:溢出修饰符,须搭配对齐关键字。safe 在放不下时改回起点对齐。移动端低版本 Safari、小程序谨慎使用

align-items

网格项在格子内沿列轴对齐。水平书写时就是垂直对齐。

初始值:normal。在网格里表现与 stretch 相同。

常用值:

  • stretch:拉满格子的列轴尺寸。
  • start:靠列轴起点(水平书写时相当于顶部)。
  • end:靠列轴终点(水平书写时相当于底部)。
  • center:列轴居中。
  • baseline:按第一行文字基线对齐。

其余取值(存在浏览器兼容限制):

  • self-startself-end:跟项目自身书写方向对齐。
  • first baselinelast baseline:显式指定第一、最后基线;baseline 等同于 first baseline
  • flex-startflex-end:在 Grid 里分别等同于 startend
  • safeunsafe:含义与 justify-items 相同。

place-items

align-itemsjustify-items 的简写:第一个值给列轴,第二个值给行轴。

place-items: <align-items> <justify-items>;

只写一个值且对两个属性都合法时,两轴都用它。

justify-content

所有列轨道在容器内沿行轴怎么分布。列宽总和小于容器时才看得出效果。

初始值:normal

常用值:

  • start:列轨道靠容器行轴起点(水平书写时相当于左)。
  • end:靠行轴终点。
  • center:行轴居中。
  • space-between:首尾贴边,列与列间隔相等。
  • space-around:每列两侧间隔相等,因此列与列之间的间隔是列与边缘的两倍。
  • space-evenly:列与列、列与边缘的间隔都相等。
  • stretch:把 auto 列拉宽,填满容器。

其余取值(存在浏览器兼容限制):

  • leftright:物理左、右。
  • flex-startflex-end:在 Grid 里分别等同于 startend
  • safeunsafe:溢出修饰符。

align-content

所有行轨道在容器内沿列轴怎么分布。行高总和小于容器时才看得出效果。

初始值:normal

常用值:

  • start:行轨道靠列轴起点(水平书写时相当于顶部)。
  • end:靠列轴终点。
  • center:列轴居中。
  • space-between:首尾贴边,行与行间隔相等。
  • space-around:每行两侧间隔相等。
  • space-evenly:行与行、行与边缘的间隔都相等。
  • stretch:把 auto 行拉高,填满容器。

其余取值(存在浏览器兼容限制):

  • flex-startflex-end:在 Grid 里分别等同于 startend
  • baselinefirst baselinelast baseline:按行基线对齐。
  • safeunsafe:溢出修饰符。

place-content

align-contentjustify-content 的简写:第一个值给列轴,第二个值给行轴。

place-content: <align-content> <justify-content>;

只写一个值且对两个属性都合法时,两轴都用它。

子项目属性

设置在网格项上:

  1. grid-row-startgrid-row-endgrid-column-startgrid-column-end
  2. grid-rowgrid-columngrid-area
  3. justify-selfalign-selfplace-self
  4. z-indexorder

grid-row-start、grid-row-end

指定网格项的起始、结束行线

初始值:auto(交给 grid-auto-flow 自动放置,跨度相当于 span 1)。

常用值:

  • auto:自动放置。
  • 整数:第几条行线,如 grid-row-start: 2。负数从显式网格末尾倒数,不算后面多出来的隐式轨道。
  • span <integer>:跨越指定条数的行,如 grid-row-end: span 2

其余取值(存在浏览器兼容限制):

  • custom-ident:用命名行线,如 grid-row-start: header
  • integer custom-ident:第 n 条叫这个名字的线,如 grid-row-start: 2 content
  • span custom-identspan integer custom-ident:按名字跨越。

规则:

  • 起始线编号大于结束线时,浏览器对调两端。
  • 只写 grid-row-start 时,结束线按 auto(跨 1 行)。
  • span 多写在结束线上;写在起始线上表示从结束线往回跨。

grid-column-start、grid-column-end

指定起始、结束列线。语法、取值、规则与 grid-row-* 对称。

grid-row、grid-column

分别是行线、列线起止的简写。

grid-row: <grid-row-start> / <grid-row-end>;
grid-column: <grid-column-start> / <grid-column-end>;

grid-area

两种用法:行列定位区域名称

行列定位,顺序是行起、列起、行止、列止:

grid-area: <row-start> / <col-start> / <row-end> / <col-end>;

区域名称,配合 grid-template-areas

.grid {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

justify-self、align-self、place-self

单个项目覆盖容器上的 justify-itemsalign-items

初始值:auto(采用容器上的对应属性)。其余常用值、其余取值与 justify-itemsalign-items 相同。

place-self: <align-self> <justify-self>;

z-index

网格项可以重叠,用 z-index 比谁在上面。数值越大越靠上。非 autoz-index 会让该网格项形成层叠上下文

order

只影响自动放置时谁先填格子,以及 z-index 同为 auto 时谁先绘制。初始值 0,可取负。数值越小越早放置、绘制越靠下。已经用 grid-rowgrid-columngrid-area 钉死坐标的项,格子位置不受 order 改动。Tab 顺序和读屏仍跟源码走。

常见问题

Grid 容器内的子项目是流式布局吗?

不是普通流,也不是 Flex 那种沿一根轴依次排。Grid 是二维落位:坐标来自网格线或命名区域,项目可以重叠。

没写坐标时,浏览器按 grid-auto-flow(以及 order依 DOM 顺序填格子。这是在往单元格里填,不是文档流那种一个接一个挤、挤不下就换行。自动放置会用到 DOM 顺序,但排版模型仍是网格。

隐式网格行、列是如何触发的?

网格项落到显式网格外面,或自动放置把显式格子用完,浏览器就补隐式行、列。尺寸分别听 grid-auto-rowsgrid-auto-columns

subgrid

subgrid 让子网格沿某一方向沿用父网格的轨道(含间隙),嵌套时才能和父级格子对齐。子项自己要先跨过父级的多条轨道,再在那一向上写 subgrid。行、列可以分别设。

.child {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: span 3;
}

其余取值(存在浏览器兼容限制):Firefox 71+、Safari 16+、Chrome 117+。IE11、旧版 Safari 不支持。需要嵌套对齐又要兼容旧环境时,把轨道尺寸在子级再写一遍。

小结

Grid 先画轨道和间隙,再让项目按线或按区域落位。显式轨道是画好的格子,越界和自动放置会长出隐式轨道。对齐要分清是「在各自格子里」还是「整张网格在容器里」。

参考资料

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-08-18 22:07:38

results matching ""

    No results matching ""