CSS Grid Layout(网格布局)是一个强大的二维布局系统,可以让你轻松地创建复杂的网页布局。
下面内容分为两个主要部分:
- 网格容器 (Grid Container) 的属性:应用在父元素上的属性,用于定义网格结构和整体对齐方式。
- 网格项目 (Grid Item) 的属性:应用在子元素上的属性,用于定义单个项目在网格中的位置和对齐方式。
准备工作:HTML 结构
我们先定义一个基本的 HTML 结构,用于后续所有的 CSS 示例。
xml
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Grid 布局详解</title>
<style>
/* 通用样式,方便观察 */
.grid-container {
border: 2px solid black;
padding: 10px;
margin-bottom: 20px; /* 分隔不同示例 */
background-color: lightgrey;
}
.grid-item {
border: 1px solid firebrick;
background-color: lightcoral;
padding: 20px;
text-align: center;
font-size: 1.2em;
color: white;
}
/* 为不同的项目添加一点区分 */
.item-1 { background-color: #e67e22; }
.item-2 { background-color: #2ecc71; }
.item-3 { background-color: #3498db; }
.item-4 { background-color: #9b59b6; }
.item-5 { background-color: #f1c40f; }
.item-6 { background-color: #1abc9c; }
.item-7 { background-color: #e74c3c; }
.item-8 { background-color: #34495e; }
.item-9 { background-color: #7f8c8d; }
.item-10 { background-color: #d35400; }
.item-11 { background-color: #27ae60; }
.item-12 { background-color: #2980b9; }
</style>
</head>
<body>
<h1>CSS Grid 布局详解</h1>
<!-- 后续的示例将使用类似下面的结构 -->
<!--
<div class="grid-container [specific-class-for-example]">
<div class="grid-item item-1">项目 1</div>
<div class="grid-item item-2">项目 2</div>
<div class="grid-item item-3">项目 3</div>
...
</div>
-->
</body>
</html>
第一部分:网格容器 (Grid Container) 属性
这些属性应用在设置了 display: grid
或 display: inline-grid
的元素上。
1. display
display: grid;
: 将元素定义为块级网格容器。display: inline-grid;
: 将元素定义为内联级网格容器。
xml
<!-- display: grid 示例 -->
<h2>1. display: grid</h2>
<div class="grid-container display-grid-example">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
<div class="grid-item item-4">4</div>
</div>
<style>
.display-grid-example {
display: grid;
/* 为了看到效果,我们先简单定义列和行 */
grid-template-columns: 100px 100px;
grid-template-rows: 50px 50px;
}
</style>
<!-- display: inline-grid 示例 -->
<h2>1. display: inline-grid</h2>
<p>
这是一个内联网格容器:
<span class="grid-container display-inline-grid-example">
<span class="grid-item item-1">1</span>
<span class="grid-item item-2">2</span>
<span class="grid-item item-3">3</span>
<span class="grid-item item-4">4</span>
</span>
它会和旁边的文字排在一起。
</p>
<style>
.display-inline-grid-example {
display: inline-grid; /* 注意这里是 inline-grid */
grid-template-columns: 60px 60px;
grid-template-rows: 40px 40px;
vertical-align: middle; /* 方便观察内联效果 */
}
.display-inline-grid-example .grid-item {
padding: 5px; /* 调整内联网格项的内边距 */
font-size: 1em;
}
</style>
2. grid-template-columns
和 grid-template-rows
定义网格的列和行的大小和数量。
- 固定单位 :
px
,em
,rem
等。 - 百分比 :
%
相对于容器尺寸。 fr
单位: (fractional unit) 代表网格容器中可用空间的一等份。auto
: 由内容或grid-auto-*
属性决定大小。minmax(min, max)
: 定义一个长度范围,表示列/行宽(高)不能小于 min,不能大于 max。repeat(count, sizes)
: 重复定义列或行。count
可以是数字,也可以是auto-fill
或auto-fit
。fit-content(limit)
: 将轨道大小限制在limit
和auto
(基于内容)之间。
xml
<!-- grid-template-columns / grid-template-rows 示例 -->
<h2>2. grid-template-columns / grid-template-rows</h2>
<h3>2.1 固定单位 (px) 和 百分比 (%)</h3>
<div class="grid-container template-px-percent">
<div class="grid-item item-1">1 (100px)</div>
<div class="grid-item item-2">2 (50%)</div>
<div class="grid-item item-3">3 (150px)</div>
<div class="grid-item item-4">4 (Row 1: 80px)</div>
<div class="grid-item item-5">5</div>
<div class="grid-item item-6">6 (Row 2: 120px)</div>
</div>
<style>
.template-px-percent {
display: grid;
grid-template-columns: 100px 50% 150px; /* 第1列100px, 第2列占容器宽度50%, 第3列150px */
grid-template-rows: 80px 120px; /* 第1行高80px, 第2行高120px */
}
</style>
<h3>2.2 fr 单位</h3>
<div class="grid-container template-fr">
<div class="grid-item item-1">1 (1fr)</div>
<div class="grid-item item-2">2 (2fr)</div>
<div class="grid-item item-3">3 (1fr)</div>
<div class="grid-item item-4">4 (Row 1: auto)</div>
<div class="grid-item item-5">5</div>
<div class="grid-item item-6">6 (Row 2: 100px)</div>
</div>
<style>
.template-fr {
display: grid;
/* 总可用宽度分为 1fr + 2fr + 1fr = 4份 */
/* 第1列占1/4, 第2列占2/4, 第3列占1/4 */
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: auto 100px; /* 第1行高度由内容决定, 第2行100px */
}
</style>
<h3>2.3 minmax() 函数</h3>
<div class="grid-container template-minmax">
<div class="grid-item item-1">1 (minmax(100px, 1fr))</div>
<div class="grid-item item-2">2 (200px)</div>
<div class="grid-item item-3">3 (minmax(150px, 300px))</div>
</div>
<style>
.template-minmax {
display: grid;
/* 第1列:最小100px,最大1fr (占用剩余空间) */
/* 第2列:固定200px */
/* 第3列:最小150px,最大300px */
grid-template-columns: minmax(100px, 1fr) 200px minmax(150px, 300px);
grid-template-rows: 100px;
}
</style>
<h3>2.4 repeat() 函数</h3>
<div class="grid-container template-repeat">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
<div class="grid-item item-4">4</div>
<div class="grid-item item-5">5</div>
<div class="grid-item item-6">6</div>
</div>
<style>
.template-repeat {
display: grid;
/* 定义3列,每列都是 1fr */
grid-template-columns: repeat(3, 1fr);
/* 定义2行,模式为:50px, 100px, 50px, 100px... */
grid-template-rows: repeat(2, 50px 100px); /* 这里会创建4行 */
}
</style>
<h3>2.5 repeat() 与 auto-fill / auto-fit</h3>
<p>尝试改变浏览器窗口大小查看效果。</p>
<h4>auto-fill: 尽可能多地填充列,即使是空的</h4>
<div class="grid-container template-autofill">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
</div>
<style>
.template-autofill {
display: grid;
/* 自动填充列,每列最小120px,最大1fr */
/* auto-fill 会创建尽可能多的轨道,即使没有项目填充它们 */
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
grid-template-rows: 80px;
}
</style>
<h4>auto-fit: 尽可能多地填充列,但会折叠空列</h4>
<div class="grid-container template-autofit">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
</div>
<style>
.template-autofit {
display: grid;
/* 自动适应列,每列最小120px,最大1fr */
/* auto-fit 会将空的轨道折叠为0,让有内容的轨道占据更多空间 */
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
grid-template-rows: 80px;
}
</style>
<h3>2.6 命名网格线 (Named Grid Lines)</h3>
<div class="grid-container template-named-lines">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
<div class="grid-item item-4">4</div>
</div>
<style>
.template-named-lines {
display: grid;
/* 在定义轨道尺寸的同时,用 [] 定义线的名字 */
grid-template-columns: [col-start] 1fr [col-mid] 1fr [col-end];
grid-template-rows: [row-start] 100px [row-mid] auto [row-end];
/* 多个名字用空格隔开: [line-name-1 line-name-2] */
/* grid-template-columns: [start main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end end]; */
}
/* 如何使用命名线将在 grid-column/grid-row 中演示 */
</style>
3. grid-template-areas
允许你通过引用预定义的网格区域名称来放置网格项目。
- 用字符串定义每一行。
- 字符串中的每个单词代表一个单元格,并对应一个区域名称。
- 使用
.
表示一个空单元格。 - 相同名称的区域必须形成一个矩形。
xml
<!-- grid-template-areas 示例 -->
<h2>3. grid-template-areas</h2>
<div class="grid-container template-areas-example">
<header class="grid-item item-1 area-header">Header</header>
<nav class="grid-item item-2 area-nav">Nav</nav>
<main class="grid-item item-3 area-main">Main Content</main>
<aside class="grid-item item-4 area-sidebar">Sidebar</aside>
<footer class="grid-item item-5 area-footer">Footer</footer>
<!-- 注意:HTML结构中的顺序不重要,CSS中的 grid-area 属性才决定位置 -->
</div>
<style>
.template-areas-example {
display: grid;
height: 400px; /* 给容器一个高度以便观察 */
/* 定义列宽和行高 */
grid-template-columns: 150px 1fr 150px; /* 左侧导航窄,中间内容宽,右侧边栏窄 */
grid-template-rows: auto 1fr auto; /* 头部自适应,中间占满剩余,底部自适应 */
/* 定义网格区域布局 */
grid-template-areas:
"header header header" /* 第1行:header 区域横跨3列 */
"nav main sidebar" /* 第2行:nav, main, sidebar 各占1列 */
"footer footer footer"; /* 第3行:footer 区域横跨3列 */
gap: 10px; /* 加点间隙更好看 */
}
/* 使用 grid-area 属性将项目分配到对应的区域 (后面会详细讲 grid-area) */
.area-header { grid-area: header; background-color: #16a085; }
.area-nav { grid-area: nav; background-color: #27ae60; }
.area-main { grid-area: main; background-color: #2980b9; }
.area-sidebar{ grid-area: sidebar;background-color: #8e44ad; }
.area-footer { grid-area: footer; background-color: #2c3e50; }
</style>
<h3>3.1 使用 `.` 表示空单元格</h3>
<div class="grid-container template-areas-dot">
<div class="grid-item item-1 area-a">A</div>
<div class="grid-item item-2 area-b">B</div>
<div class="grid-item item-3 area-c">C</div>
</div>
<style>
.template-areas-dot {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 100px);
grid-template-areas:
"a . b" /* 第1行:A 在第1列,第2列空,B 在第3列 */
"a c c"; /* 第2行:A 在第1列,C 横跨第2、3列 */
gap: 5px;
}
.area-a { grid-area: a; }
.area-b { grid-area: b; }
.area-c { grid-area: c; }
</style>
4. grid-template
grid-template-rows
, grid-template-columns
, 和 grid-template-areas
的简写属性。
语法比较复杂,通常是先定义 grid-template-areas
,然后在每行字符串旁边加上行高定义,最后在末尾加上 /
和列宽定义。
xml
<!-- grid-template 示例 -->
<h2>4. grid-template (简写)</h2>
<div class="grid-container template-shorthand">
<header class="grid-item item-1 area-header-sh">Header</header>
<main class="grid-item item-3 area-main-sh">Main</main>
<footer class="grid-item item-5 area-footer-sh">Footer</footer>
</div>
<style>
.template-shorthand {
display: grid;
height: 300px;
gap: 10px;
/* 简写形式 */
grid-template:
[row1-start] "header header" auto [row1-end] /* 第1行: 区域"header", 高度auto */
[row2-start] "main main" 1fr [row2-end] /* 第2行: 区域"main", 高度1fr */
[row3-start] "footer footer" 50px [row3-end] /* 第3行: 区域"footer", 高度50px */
/ 1fr 1fr; /* 列宽定义: 两列,每列1fr */
/* 注意:行名 [row-name] 是可选的 */
/* 格式: [row-name]? "areas" row-size? [row-name]? ... / col-sizes */
}
/* 分配区域 */
.area-header-sh { grid-area: header; background-color: #1abc9c;}
.area-main-sh { grid-area: main; background-color: #3498db;}
.area-footer-sh { grid-area: footer; background-color: #95a5a6;}
</style>
5. grid-column-gap
和 grid-row-gap
(以及 gap
/ grid-gap
)
定义网格线之间的间隙(Gutter)。
grid-column-gap
: 定义列间隙。grid-row-gap
: 定义行间隙。grid-gap
:grid-row-gap
和grid-column-gap
的简写。grid-gap: <row-gap> <column-gap>;
如果只提供一个值,则行列间隙相同。gap
: 最新的标准写法,是grid-gap
的别名,也适用于 Flexbox。推荐使用gap
。gap: <row-gap> <column-gap>;
xml
<!-- gap 示例 -->
<h2>5. gap / grid-gap (间隙)</h2>
<div class="grid-container gap-example">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
<div class="grid-item item-4">4</div>
<div class="grid-item item-5">5</div>
<div class="grid-item item-6">6</div>
</div>
<style>
.gap-example {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 100px);
/* 老语法 */
/* grid-row-gap: 20px; */
/* grid-column-gap: 10px; */
/* grid-gap: 20px 10px; */ /* row-gap column-gap */
/* grid-gap: 15px; */ /* row-gap 和 column-gap 都是 15px */
/* 新语法 (推荐) */
/* row-gap: 20px; */
/* column-gap: 10px; */
gap: 20px 10px; /* row-gap column-gap */
/* gap: 15px; */ /* row-gap 和 column-gap 都是 15px */
}
</style>
6. justify-items
定义网格项目在其单元格内部沿**行轴(内联轴/水平方向)**的对齐方式。应用于所有网格项目。
start
: 对齐到单元格的起始边缘。end
: 对齐到单元格的结束边缘。center
: 对齐到单元格的中心。stretch
(默认值): 项目填充整个单元格的宽度。
xml
<!-- justify-items 示例 -->
<h2>6. justify-items (项目水平对齐)</h2>
<div class="grid-container justify-items-example">
<div class="grid-item item-1">Start</div>
<div class="grid-item item-2">End</div>
<div class="grid-item item-3">Center</div>
<div class="grid-item item-4">Stretch (Default)</div>
</div>
<style>
.justify-items-example {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 4列,每列宽度相同 */
grid-template-rows: 100px; /* 1行,高度100px */
gap: 10px;
/* 设置不同的 justify-items 值 */
/* justify-items: start; */
/* justify-items: end; */
/* justify-items: center; */
justify-items: stretch; /* 默认值 */
/* 为了演示效果,我们给每个 item 单独设置 (通常是在容器上设置一个值) */
/* 这里我们用 justify-self 来覆盖演示 */
}
.justify-items-example .item-1 { justify-self: start; } /* 覆盖容器设置 */
.justify-items-example .item-2 { justify-self: end; } /* 覆盖容器设置 */
.justify-items-example .item-3 { justify-self: center; } /* 覆盖容器设置 */
.justify-items-example .item-4 { justify-self: stretch; }/* 覆盖容器设置 (默认) */
/* 为了让非 stretch 生效,项目需要有固有宽度或不被拉伸 */
/* 在这里,默认情况下项目会拉伸,所以 start/end/center 看起来像是有外边距 */
/* 如果项目设置了宽度,效果更明显 */
.justify-items-example .grid-item {
width: 80px; /* 给项目一个固定宽度,这样对齐效果更清晰 */
/* 注意:设置了 width 后,stretch 也会表现得像 start,因为它无法拉伸 */
/* 为了演示 stretch,我们移除第四个项目的宽度 */
}
.justify-items-example .item-4 {
width: auto; /* 移除宽度,允许 stretch 生效 */
}
</style>
7. align-items
定义网格项目在其单元格内部沿**列轴(块轴/垂直方向)**的对齐方式。应用于所有网格项目。
start
: 对齐到单元格的顶部边缘。end
: 对齐到单元格的底部边缘。center
: 对齐到单元格的垂直中心。stretch
(默认值): 项目填充整个单元格的高度。baseline
: 对齐到项目内容的基线。
css
<!-- align-items 示例 -->
<h2>7. align-items (项目垂直对齐)</h2>
<div class="grid-container align-items-example">
<div class="grid-item item-1" style="font-size: 1em; height: auto;">Start<br>Line 2</div>
<div class="grid-item item-2" style="font-size: 1.5em; height: auto;">End</div>
<div class="grid-item item-3" style="font-size: 1em; height: auto;">Center</div>
<div class="grid-item item-4" style="font-size: 1.2em;">Stretch (Default)</div>
<div class="grid-item item-5" style="font-size: 2em; height: auto;">Baseline</div>
<div class="grid-item item-6" style="font-size: 1em; height: auto;">Baseline Ref</div>
</div>
<style>
.align-items-example {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 150px 150px; /* 行高设大一点方便观察 */
gap: 10px;
/* 设置不同的 align-items 值 */
/* align-items: start; */
/* align-items: end; */
/* align-items: center; */
/* align-items: stretch; */ /* 默认值 */
align-items: baseline; /* 演示 baseline */
/* 为了演示效果,我们给每个 item 单独设置 (通常是在容器上设置一个值) */
/* 这里我们用 align-self 来覆盖演示 */
/* 注意:要使非 stretch 生效,项目通常需要有固有高度或设置 height: auto */
}
.align-items-example .item-1 { align-self: start; }
.align-items-example .item-2 { align-self: end; }
.align-items-example .item-3 { align-self: center; }
.align-items-example .item-4 { align-self: stretch; height: auto; /* 允许拉伸 */}
.align-items-example .item-5 { align-self: baseline; } /* 参与基线对齐 */
.align-items-example .item-6 { align-self: baseline; } /* 参与基线对齐 */
</style>
8. place-items
align-items
和 justify-items
的简写。
place-items: <align-items> <justify-items>;
- 如果只提供一个值,则
align-items
和justify-items
都使用该值。 - 例如
place-items: center;
等同于align-items: center; justify-items: center;
- 例如
place-items: start end;
等同于align-items: start; justify-items: end;
xml
<!-- place-items 示例 -->
<h2>8. place-items (项目对齐简写)</h2>
<div class="grid-container place-items-example">
<div class="grid-item item-1">Center Center</div>
<div class="grid-item item-2" style="width: 80px; height: 50px;">Start End</div>
<div class="grid-item item-3" style="width: 100px; height: auto;">Stretch Center</div>
</div>
<style>
.place-items-example {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 150px;
gap: 10px;
/* place-items: center; */ /* align: center, justify: center */
/* place-items: start end; */ /* align: start, justify: end */
place-items: stretch center; /* align: stretch, justify: center */
/* 为了演示,我们给项目设置了不同的宽高 */
}
/* 注意:place-items 设置的是容器级别所有项目的默认对齐方式 */
/* 可以通过 align-self / justify-self / place-self 在项目级别覆盖 */
</style>
9. justify-content
当网格的总宽度小于网格容器的宽度时,定义网格轨道(作为一个整体)在容器内沿**行轴(水平方向)**的对齐方式。
start
(默认值): 网格向容器的起始位置对齐。end
: 网格向容器的结束位置对齐。center
: 网格在容器中居中对齐。stretch
: 拉伸网格轨道以填满容器宽度(仅适用于auto
尺寸的轨道)。space-around
: 每个网格轨道两侧分配相等的空间,容器边缘的空间是轨道之间空间的一半。space-between
: 第一个轨道贴近容器起始边缘,最后一个轨道贴近容器结束边缘,剩余空间平均分配到轨道之间。space-evenly
: 每个网格轨道之间以及轨道与容器边缘之间的空间都相等。
xml
<!-- justify-content 示例 -->
<h2>9. justify-content (网格水平对齐)</h2>
<p>需要网格总宽度小于容器宽度才能看到效果。</p>
<div class="grid-container justify-content-example">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
</div>
<style>
.justify-content-example {
display: grid;
width: 600px; /* 容器宽度 */
height: 150px;
grid-template-columns: 100px 100px 100px; /* 网格总宽度 300px + gap */
grid-template-rows: 80px;
gap: 10px; /* 间隙也会占用空间 (300 + 10 + 10 = 320px) */
/* 尝试以下值 */
/* justify-content: start; */ /* 默认 */
/* justify-content: end; */
/* justify-content: center; */
/* justify-content: space-around; */
/* justify-content: space-between; */
justify-content: space-evenly;
/* justify-content: stretch; */ /* 对固定宽度的列无效 */
}
</style>
10. align-content
当网格的总高度小于网格容器的高度时,定义网格轨道(作为一个整体)在容器内沿**列轴(垂直方向)**的对齐方式。
start
(默认值): 网格向容器的顶部对齐。end
: 网格向容器的底部对齐。center
: 网格在容器中垂直居中对齐。stretch
: 拉伸网格轨道以填满容器高度(仅适用于auto
尺寸的轨道)。space-around
: 每个网格轨道上下两侧分配相等的空间,容器边缘的空间是轨道之间空间的一半。space-between
: 第一行轨道贴近容器顶部边缘,最后一行轨道贴近容器底部边缘,剩余空间平均分配到轨道之间。space-evenly
: 每个网格轨道之间以及轨道与容器边缘之间的空间都相等。
xml
<!-- align-content 示例 -->
<h2>10. align-content (网格垂直对齐)</h2>
<p>需要网格总高度小于容器高度才能看到效果。</p>
<div class="grid-container align-content-example">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
<div class="grid-item item-4">4</div>
<div class="grid-item item-5">5</div>
<div class="grid-item item-6">6</div>
</div>
<style>
.align-content-example {
display: grid;
height: 400px; /* 容器高度 */
grid-template-columns: 100px 100px 100px;
grid-template-rows: 80px 80px; /* 网格总高度 160px + gap */
gap: 10px; /* 间隙也会占用空间 (160 + 10 = 170px) */
/* 尝试以下值 */
/* align-content: start; */ /* 默认 */
/* align-content: end; */
/* align-content: center; */
/* align-content: space-around; */
/* align-content: space-between; */
align-content: space-evenly;
/* align-content: stretch; */ /* 对固定高度的行无效 */
}
</style>
11. place-content
align-content
和 justify-content
的简写。
place-content: <align-content> <justify-content>;
- 如果只提供一个值,则
align-content
和justify-content
都使用该值。 - 例如
place-content: center;
等同于align-content: center; justify-content: center;
- 例如
place-content: space-between end;
等同于align-content: space-between; justify-content: end;
xml
<!-- place-content 示例 -->
<h2>11. place-content (网格对齐简写)</h2>
<div class="grid-container place-content-example">
<div class="grid-item item-1">1</div>
<div class="grid-item item-2">2</div>
<div class="grid-item item-3">3</div>
<div class="grid-item item-4">4</div>
</div>
<style>
.place-content-example {
display: grid;
width: 500px; /* 容器尺寸大于网格尺寸 */
height: 300px;
grid-template-columns: 100px 100px; /* 网格宽度 200px + gap */
grid-template-rows: 60px 60px; /* 网格高度 120px + gap */
gap: 10px; /* 宽度 210px, 高度 130px */
/* place-content: center; */ /* 垂直居中 & 水平居中 */
place-content: space-between end; /* 垂直 space-between & 水平 end */
/* place-content: start space-evenly; */ /* 垂直 start & 水平 space-evenly */
}
</style>
12. grid-auto-columns
和 grid-auto-rows
指定隐式创建的网格轨道(行或列)的大小。当网格项目放置在显式定义的网格范围之外时,就会创建隐式轨道。
xml
<!-- grid-auto-columns / grid-auto-rows 示例 -->
<h2>12. grid-auto-columns / grid-auto-rows</h2>
<div class="grid-container auto-tracks-example">
<div class="grid-item item-1">1 (Explicit)</div>
<div class="grid-item item-2">2 (Explicit)</div>
<div class="grid-item item-3" style="grid-column: 3;">3 (Implicit Col)</div>
<div class="grid-item item-4" style="grid-row: 3;">4 (Implicit Row)</div>
<div class="grid-item item-5" style="grid-column: 4; grid-row: 4;">5 (Implicit Col & Row)</div>
</div>
<style>
.auto-tracks-example {
display: grid;
/* 显式定义 2x2 网格 */
grid-template-columns: 100px 100px;
grid-template-rows: 80px 80px;
gap: 5px;
/* 定义隐式创建的列的宽度 */
grid-auto-columns: 60px; /* 比如第3, 4列创建时宽度为60px */
/* 定义隐式创建的行的高度 */
grid-auto-rows: 40px; /* 比如第3, 4行创建时高度为40px */
}
</style>
13. grid-auto-flow
控制没有明确放置位置的网格项目(自动放置的项目)如何流入网格。
row
(默认值): 自动放置的项目按顺序填充每一行,必要时添加新行。column
: 自动放置的项目按顺序填充每一列,必要时添加新列。dense
: "密集"打包算法。如果后面出现了较小的项目,它会尝试填补网格中较早出现的空白,可能导致项目顺序看起来被打乱,但布局更紧凑。
xml
<!-- grid-auto-flow 示例 -->
<h2>13. grid-auto-flow</h2>
<h3>13.1 auto-flow: row (默认)</h3>
<div class="grid-container autoflow-row-example">
<div class="grid-item item-1" style="grid-column: 1 / 3;">1 (Span 2 cols)</div>
<div class="grid-item item-2">2 (Auto)</div>
<div class="grid-item item-3">3 (Auto)</div>
<div class="grid-item item-4">4 (Auto)</div>
</div>
<style>
.autoflow-row-example {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(2, 80px);
grid-auto-flow: row; /* 默认值,按行填充 */
gap: 5px;
/* 结果: */
/* Item 1 占据 (1,1) 和 (1,2) */
/* Item 2 放在 (1,3) */
/* Item 3 放在 (2,1) */
/* Item 4 放在 (2,2) */
}
</style>
<h3>13.2 auto-flow: column</h3>
<div class="grid-container autoflow-column-example">
<div class="grid-item item-1" style="grid-row: 1 / 3;">1 (Span 2 rows)</div>
<div class="grid-item item-2">2 (Auto)</div>
<div class="grid-item item-3">3 (Auto)</div>
<div class="grid-item item-4">4 (Auto)</div>
</div>
<style>
.autoflow-column-example {
display: grid;
grid-template-columns: repeat(2, 100px);
grid-template-rows: repeat(3, 80px);
grid-auto-flow: column; /* 按列填充 */
gap: 5px;
/* 结果: */
/* Item 1 占据 (1,1) 和 (2,1) */
/* Item 2 放在 (3,1) */
/* Item 3 放在 (1,2) */
/* Item 4 放在 (2,2) */
}
</style>
<h3>13.3 auto-flow: dense</h3>
<div class="grid-container autoflow-dense-example">
<div class="grid-item item-1" style="grid-column: span 2;">1 (Span 2 cols)</div>
<div class="grid-item item-2">2 (Auto)</div>
<div class="grid-item item-3" style="grid-column: span 2;">3 (Span 2 cols)</div>
<div class="grid-item item-4">4 (Auto)</div>
<div class="grid-item item-5">5 (Auto)</div>
</div>
<style>
.autoflow-dense-example {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-auto-rows: 80px; /* 让自动行有高度 */
grid-auto-flow: row dense; /* 使用密集填充 */
gap: 5px;
/* 结果 (对比没有 dense 的情况): */
/* Item 1 占据 (1,1) (1,2) */
/* Item 2 占据 (1,3) */
/* Item 3 占据 (2,1) (2,2) */
/* Item 4 发现第一行 (1,3) 被 Item 2 占了,但第二行 (2,3) 是空的,于是填充 (2,3) */
/* Item 5 填充 (3,1) */
/* 如果没有 dense: Item 4 会在 (3,1), Item 5 会在 (3,2),留下 (2,3) 空白 */
}
</style>
14. grid
所有网格属性的超级简写。语法非常复杂,不常用,因为它可读性较差。它能同时设置显式网格属性 (grid-template-*
)、隐式网格属性 (grid-auto-*
) 和 grid-auto-flow
。
其复杂性超出了常规使用范畴,通常建议分别设置各个属性。如果你确实需要了解,可以查阅 MDN 文档关于 grid
简写属性的详细说明。
第二部分:网格项目 (Grid Item) 属性
这些属性应用在网格容器的直接子元素上。
1. grid-column-start
, grid-column-end
, grid-row-start
, grid-row-end
定义网格项目在网格中的位置和跨度。
- 可以接受数字(网格线编号,从 1 开始)。
- 可以接受命名网格线。
- 可以使用
span <number>
指定跨越多少个轨道。 - 可以使用
span <name>
指定跨越到名为<name>
的网格线。 -1
通常表示最后一条网格线。
xml
<!-- grid-column/row-start/end 示例 -->
<h2>15. grid-column/row-start/end</h2>
<div class="grid-container item-placement-example">
<div class="grid-item item-1 item-pos-1">1 (col 1-3, row 1)</div>
<div class="grid-item item-2 item-pos-2">2 (col 1, row 2-4)</div>
<div class="grid-item item-3 item-pos-3">3 (col 2 / span 2, row 3)</div>
<div class="grid-item item-4 item-pos-4">4 (col -1, row 1)</div>
<div class="grid-item item-5 item-pos-5">5 (col 2 / col-mid, row 2 / row-end)</div>
</div>
<style>
.item-placement-example {
display: grid;
grid-template-columns: [col1-start] 1fr [col2-start col-mid] 1fr [col3-start] 1fr [col4-start col-end] 1fr [col5-start];
grid-template-rows: [row1-start] 100px [row2-start] 100px [row3-start] 100px [row4-start row-end] 100px [row5-start];
gap: 10px;
}
.item-pos-1 {
/* 从第 1 条列线开始,到第 3 条列线结束 (跨越第1、2列) */
grid-column-start: 1;
grid-column-end: 3; /* 不包含第3条线本身,所以是第1、2列 */
/* grid-column-end: span 2; */ /* 等效:从start开始跨越2列 */
/* 行位置默认是 auto,会放在第一个可用行 */
grid-row-start: 1;
/* grid-row-end: 2; */ /* 等效 */
}
.item-pos-2 {
/* 从第 1 条列线开始 */
grid-column-start: 1;
/* 从第 2 条行线开始,到第 4 条行线结束 (跨越第2、3行) */
grid-row-start: 2;
grid-row-end: 4; /* 不包含第4条线,所以是第2、3行 */
/* grid-row-end: span 2; */ /* 等效 */
}
.item-pos-3 {
/* 从第 2 条列线开始,跨越 2 列 (即第2、3列) */
grid-column-start: 2;
grid-column-end: span 2;
/* 从第 3 条行线开始 */
grid-row-start: 3;
}
.item-pos-4 {
/* 放在最后一列 (使用负数索引) */
/* grid-column-start: 4; */ /* 等效于这个4列网格 */
grid-column-start: -1; /* 最后一条列线之前,即最后一列 */
grid-column-end: -1; /* 不好理解,通常用 start 或 span */
/* 推荐写法: */
grid-column-start: 4;
grid-column-end: 5; /* 或者 grid-column-end: span 1; */
/* 或者 grid-column: 4 / 5; */
/* 或者 grid-column: -1; */ /* 简写,表示最后一列 */
grid-row-start: 1;
}
.item-pos-5 {
/* 使用命名网格线 */
grid-column-start: col2-start; /* 或 col-mid */
grid-column-end: col-end; /* 到名为 col-end 的线结束 (跨越第2, 3, 4列) */
grid-row-start: row2-start;
grid-row-end: row-end; /* 到名为 row-end 的线结束 (跨越第2, 3行) */
}
</style>
2. grid-column
和 grid-row
分别是 grid-column-start
/ grid-column-end
和 grid-row-start
/ grid-row-end
的简写。
grid-column: <start-line> / <end-line>;
grid-row: <start-line> / <end-line>;
- 如果只提供一个值,则
end-line
默认为auto
或span 1
。 grid-column: 2 / 4;
(占据第 2、3 列)grid-column: 2 / span 3;
(从第 2 列开始,跨越 3 列,即第 2、3、4 列)grid-column: span 2;
(跨越 2 列,起始位置自动)grid-column: 3;
(占据第 3 列)grid-column: main-start / main-end;
(使用命名线)
xml
<!-- grid-column / grid-row 简写示例 -->
<h2>16. grid-column / grid-row (简写)</h2>
<div class="grid-container item-shorthand-example">
<div class="grid-item item-1 item-sh-1">1 (col 2 / 4, row 1 / 3)</div>
<div class="grid-item item-2 item-sh-2">2 (col 1, row 3 / span 2)</div>
<div class="grid-item item-3 item-sh-3">3 (col span 2 / -1, row 4)</div>
</div>
<style>
.item-shorthand-example {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 80px);
gap: 10px;
}
.item-sh-1 {
/* 列:从第2条线到第4条线 (第2、3列) */
/* 行:从第1条线到第3条线 (第1、2行) */
grid-column: 2 / 4;
grid-row: 1 / 3;
}
.item-sh-2 {
/* 列:第1列 (第1条线到第2条线) */
grid-column: 1; /* 等同于 1 / 2 */
/* 行:从第3条线开始,跨越2行 (第3、4行) */
grid-row: 3 / span 2; /* 等同于 3 / 5 */
}
.item-sh-3 {
/* 列:从自动位置开始跨越2列,并确保结束在最后一条线之前 (-1) */
/* 这个例子有点复杂:跨越2列,并且它的结束线是 col-end(-1) */
/* 假设自动放在第3列,跨2列会到第5条线,但结束线是-1(第5条),所以是第3、4列 */
/* 如果自动放在第1列,跨2列到第3条线,结束线是-1(第5条),所以还是第1、2列 */
/* 更清晰的写法可能是明确指定 start/end */
/* 这里我们简化理解:放在最后两列 */
grid-column: 3 / span 2; /* 放在第3、4列 */
/* grid-column: span 2 / -1; */ /* 尝试让它在最后两列 */
/* 行:第4行 */
grid-row: 4; /* 等同于 4 / 5 */
}
</style>
3. grid-area
可以将网格项目分配到一个由 grid-template-areas
定义的命名区域,或者作为 grid-row-start
, grid-column-start
, grid-row-end
, grid-column-end
的简写。
-
分配到命名区域 :
grid-area: <name>;
(这个<name>
必须在grid-template-areas
中定义过) -
作为位置简写 :
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
- 可以使用数字、命名线或
span
。
- 可以使用数字、命名线或
xml
<!-- grid-area 示例 -->
<h2>17. grid-area</h2>
<h3>17.1 分配到命名区域</h3>
<div class="grid-container area-assign-example">
<div class="grid-item item-1 ga-header">Header</div>
<div class="grid-item item-2 ga-main">Main</div>
<div class="grid-item item-3 ga-footer">Footer</div>
</div>
<style>
.area-assign-example {
display: grid;
height: 250px;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"head head"
"main main"
"foot foot";
gap: 5px;
}
.ga-header { grid-area: head; background-color: #f39c12; }
.ga-main { grid-area: main; background-color: #16a085; }
.ga-footer { grid-area: foot; background-color: #7f8c8d; }
</style>
<h3>17.2 作为位置简写</h3>
<div class="grid-container area-shorthand-example">
<div class="grid-item item-1 ga-pos-1">1</div>
<div class="grid-item item-2 ga-pos-2">2</div>
</div>
<style>
.area-shorthand-example {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 80px);
gap: 5px;
}
.ga-pos-1 {
/* row-start / column-start / row-end / column-end */
/* 占据第1行、第1列 到 第2行、第3列 的区域 (即第1行,第1、2列) */
grid-area: 1 / 1 / 2 / 3;
background-color: #3498db;
}
.ga-pos-2 {
/* 占据第2行、第2列 到 第4行(不存在,即最后一行)、第4列(不存在,即最后一列) 的区域 */
/* 即第2、3行,第2、3列 */
grid-area: 2 / 2 / 4 / 4;
/* 等同于: */
/* grid-row-start: 2; */
/* grid-column-start: 2; */
/* grid-row-end: 4; */
/* grid-column-end: 4; */
background-color: #e74c3c;
}
</style>
4. justify-self
覆盖容器的 justify-items
设置,单独定义某个网格项目在其单元格内沿**行轴(水平方向)**的对齐方式。
start
: 对齐到单元格的起始边缘。end
: 对齐到单元格的结束边缘。center
: 对齐到单元格的中心。stretch
(默认值,或继承自justify-items
): 项目填充整个单元格的宽度。auto
: 继承容器的justify-items
值。
xml
<!-- justify-self 示例 -->
<h2>18. justify-self (单个项目水平对齐)</h2>
<div class="grid-container justify-self-example">
<div class="grid-item item-1 js-start">Start</div>
<div class="grid-item item-2 js-end">End</div>
<div class="grid-item item-3 js-center">Center</div>
<div class="grid-item item-4 js-stretch">Stretch</div>
<div class="grid-item item-5 js-auto">Auto (Inherits Center)</div>
</div>
<style>
.justify-self-example {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: 100px;
gap: 10px;
/* 容器设置 justify-items 为 center */
justify-items: center;
}
/* 覆盖容器的设置 */
.js-start { justify-self: start; width: auto; /* 需要auto才能看到效果 */}
.js-end { justify-self: end; width: auto; }
.js-center{ justify-self: center; width: auto; } /* 与容器设置相同 */
.js-stretch{ justify-self: stretch; } /* 覆盖 center */
.js-auto { justify-self: auto; width: auto; } /* 继承容器的 center */
/* 为了让非 stretch 生效,项目需要有固有宽度或不被拉伸 */
/* 如果项目设置了 width: auto; 则对齐效果更明显 */
</style>
5. align-self
覆盖容器的 align-items
设置,单独定义某个网格项目在其单元格内沿**列轴(垂直方向)**的对齐方式。
start
: 对齐到单元格的顶部边缘。end
: 对齐到单元格的底部边缘。center
: 对齐到单元格的垂直中心。stretch
(默认值,或继承自align-items
): 项目填充整个单元格的高度。baseline
: 对齐到项目内容的基线。auto
: 继承容器的align-items
值。
xml
<!-- align-self 示例 -->
<h2>19. align-self (单个项目垂直对齐)</h2>
<div class="grid-container align-self-example">
<div class="grid-item item-1 as-start">Start</div>
<div class="grid-item item-2 as-end">End</div>
<div class="grid-item item-3 as-center">Center</div>
<div class="grid-item item-4 as-stretch">Stretch</div>
<div class="grid-item item-5 as-baseline" style="font-size: 2em;">Baseline</div>
<div class="grid-item item-6 as-auto">Auto (Inherits Center)</div>
</div>
<style>
.align-self-example {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 150px 150px; /* 行高设大一点 */
gap: 10px;
/* 容器设置 align-items 为 center */
align-items: center;
}
/* 覆盖容器的设置 */
.as-start { align-self: start; height: auto; /* 需要auto才能看到效果 */ }
.as-end { align-self: end; height: auto; }
.as-center { align-self: center; height: auto; } /* 与容器设置相同 */
.as-stretch { align-self: stretch; } /* 覆盖 center */
.as-baseline { align-self: baseline; height: auto; }
.as-auto { align-self: auto; height: auto; } /* 继承容器的 center */
/* 为了让非 stretch 生效,项目通常需要有固有高度或设置 height: auto */
</style>
6. place-self
align-self
和 justify-self
的简写。
place-self: <align-self> <justify-self>;
- 如果只提供一个值,则
align-self
和justify-self
都使用该值。 - 例如
place-self: center;
等同于align-self: center; justify-self: center;
- 例如
place-self: start end;
等同于align-self: start; justify-self: end;
xml
<!-- place-self 示例 -->
<h2>20. place-self (单个项目对齐简写)</h2>
<div class="grid-container place-self-example">
<div class="grid-item item-1 ps-center">Center Both</div>
<div class="grid-item item-2 ps-start-end">Start End</div>
<div class="grid-item item-3 ps-stretch-center">Stretch Center</div>
</div>
<style>
.place-self-example {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 150px;
gap: 10px;
/* 容器可以有自己的默认对齐,比如 */
place-items: stretch stretch;
}
.ps-center {
place-self: center; /* align: center, justify: center */
width: 80px; height: 50px; /* 给定尺寸以观察效果 */
}
.ps-start-end {
place-self: start end; /* align: start, justify: end */
width: 80px; height: 50px;
}
.ps-stretch-center {
place-self: stretch center; /* align: stretch, justify: center */
width: 80px; /* 高度会拉伸,宽度居中 */
}
</style>
总结与补充
- 显式网格 vs 隐式网格 :
grid-template-*
定义的是显式网格。当项目被放置在显式网格之外,或者使用grid-auto-flow
自动放置时,可能会创建隐式网格轨道,其大小由grid-auto-columns
和grid-auto-rows
控制。 fr
单位的计算 :fr
单位分配的是可用空间 。可用空间是指容器尺寸减去所有非灵活轨道(如px
,%
,auto
计算后的尺寸)和间隙gap
后的剩余空间。minmax()
的威力 : 结合fr
和repeat(auto-fit, ...)
或repeat(auto-fill, ...)
可以创建非常灵活和响应式的布局。例如repeat(auto-fit, minmax(200px, 1fr))
表示创建尽可能多的列,每列最小 200px,并且允许它们伸展以填充可用空间。- Subgrid (子网格) : 这是一个较新的特性 (
display: subgrid
),允许嵌套的网格容器继承其父网格容器的轨道定义。这对于需要内部元素与外部网格对齐的复杂布局非常有用。浏览器支持度正在逐步提高。 - 性能: Grid 布局通常性能良好,浏览器对其进行了优化。
- 兼容性 : 主流现代浏览器对 CSS Grid Layout 的支持已经非常好。对于旧版浏览器(如 IE11),需要使用
-ms-
前缀,并且支持的是旧版本的规范,功能有限且语法不同。