CSS Grid 布局
CSS Grid 是一种二维布局系统,它可以同时控制行和列两个方向的布局。与 Flexbox 专注于一维布局不同,Grid 更适合复杂的页面布局,如整体页面结构、网格图片展示、仪表板布局等。这两种布局方式可以结合使用,Flexbox 处理组件内部布局,Grid 处理页面整体结构。
Grid 基本概念
Grid 布局同样涉及两个核心概念:
Grid 容器:设置了 display: grid 或 display: inline-grid 的元素,它成为网格容器。
Grid 项目:Grid 容器的直接子元素,它们会按照网格布局规则排列。
Grid 布局引入了一些新的术语:
- 网格线(Grid Line):构成网格结构的分界线,水平线和垂直线
- 网格轨道(Grid Track):两条相邻网格线之间的空间,即行或列
- 网格单元格(Grid Cell):行和列交叉形成的最小单位
- 网格区域(Grid Area):由多个单元格组成的矩形区域
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
}
定义网格
grid-template-columns 定义列
grid-template-columns 定义列的数量和宽度:
/* 固定宽度 */
.container {
grid-template-columns: 200px 200px 200px; /* 三列,每列 200px */
}
/* 百分比 */
.container {
grid-template-columns: 25% 50% 25%;
}
/* fr 单位(比例份数) */
.container {
grid-template-columns: 1fr 2fr 1fr; /* 中间列是两侧的两倍宽 */
}
/* 混合使用 */
.container {
grid-template-columns: 200px 1fr 200px; /* 固定-自适应-固定 */
}
/* repeat 函数 */
.container {
grid-template-columns: repeat(3, 1fr); /* 三列等宽 */
grid-template-columns: repeat(3, 100px 50px); /* 重复模式 */
}
/* auto-fill 自动填充 */
.container {
grid-template-columns: repeat(auto-fill, 200px); /* 自动填充 200px 列 */
}
/* auto-fit 自动适应 */
.container {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
fr 单位是 Grid 特有的,表示可用空间的一份。1fr 2fr 表示第二个列是第一个列的两倍宽。
auto-fill 和 auto-fit 的区别:auto-fill 会创建空列以填充容器,auto-fit 会将现有列拉伸以填满容器。结合 minmax() 可以实现响应式网格:
.responsive-grid {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
/* 每列最小 250px,最大等分,自动适应容器宽度 */
}
grid-template-rows 定义行
grid-template-rows 定义行的数量和高度:
.container {
grid-template-rows: 100px 200px 100px; /* 三行 */
grid-template-rows: auto auto; /* 两行,高度由内容决定 */
grid-template-rows: 1fr 2fr; /* 比例高度 */
}
通常只定义列,让行高由内容自动决定。如果需要固定行高或比例,才显式定义行。
grid-template-areas 命名区域
grid-template-areas 使用命名的方式定义网格结构:
.container {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 40px;
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; }
命名区域让布局直观可读。. 表示空白单元格:
grid-template-areas:
"header header header"
"sidebar . main"
"footer footer footer";
grid-template 简写
grid-template 是 grid-template-rows、grid-template-columns、grid-template-areas 的简写:
.container {
grid-template:
"header header" 60px
"sidebar main" 1fr
"footer footer" 40px
/ 200px 1fr;
}
grid 间距
gap 设置网格项之间的间距:
.container {
gap: 20px; /* 行和列间距相同 */
gap: 20px 10px; /* 行间距 列间距 */
row-gap: 20px; /* 单独设置行间距 */
column-gap: 10px; /* 单独设置列间距 */
}
项目放置
基于网格线的放置
Grid 线从 1 开始编号,也可以用负数从末尾计数(-1 是最后一条线):
.item {
/* 跨越列 */
grid-column-start: 1;
grid-column-end: 3;
/* 简写 */
grid-column: 1 / 3;
grid-column: 1 / span 2; /* 从 1 开始跨越 2 列 */
/* 跨越行 */
grid-row-start: 1;
grid-row-end: 2;
/* 简写 */
grid-row: 1 / 2;
}
常用写法:
/* 占满第一行 */
.header {
grid-column: 1 / -1; /* 从第一条到最后一条 */
}
/* 跨越两列 */
.wide {
grid-column: span 2; /* 跨越 2 列,保持起始位置 */
}
/* 固定位置 */
.positioned {
grid-column: 2;
grid-row: 1 / 3;
}
基于区域的放置
使用 grid-area 将项目放入命名区域:
.container {
display: grid;
grid-template-areas:
"header header"
"nav main"
"footer footer";
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.footer { grid-area: footer; }
grid-area 也可以用作 grid-row-start、grid-column-start、grid-row-end、grid-column-end 的简写:
.item {
grid-area: 1 / 1 / 3 / 4;
/* row-start / column-start / row-end / column-end */
}
对齐方式
容器对齐
与 Flexbox 类似,Grid 也有对齐属性:
/* 项目在单元格内的对齐 */
.container {
justify-items: start; /* 水平起点对齐 */
justify-items: end; /* 水平终点对齐 */
justify-items: center; /* 水平居中 */
justify-items: stretch; /* 水平拉伸(默认) */
align-items: start; /* 垂直起点对齐 */
align-items: end; /* 垂直终点对齐 */
align-items: center; /* 垂直居中 */
align-items: stretch; /* 垂直拉伸(默认) */
place-items: center; /* align-items justify-items 简写 */
}
/* 整个网格在容器内的对齐 */
.container {
justify-content: start; /* 网格水平靠左 */
justify-content: center; /* 网格水平居中 */
justify-content: space-between; /* 网格两端分布 */
align-content: start; /* 网格垂直靠上 */
align-content: center; /* 网格垂直居中 */
place-content: center; /* align-content justify-content 简写 */
}
justify-items 控制所有项目在各自单元格内的水平对齐,align-items 控制垂直对齐。
justify-content 控制整个网格在容器内的水平位置,当网格总宽度小于容器宽度时生效。
项目对齐
单个项目可以覆盖容器的对齐设置:
.item {
justify-self: start; /* 水平起点对齐 */
align-self: center; /* 垂直居中 */
place-self: center; /* 简写 */
}
自动布局
grid-auto-flow 自动流
grid-auto-flow 控制自动放置项目的方向:
.container {
grid-auto-flow: row; /* 按行填充(默认) */
grid-auto-flow: column; /* 按列填充 */
grid-auto-flow: dense; /* 紧凑填充,可能改变顺序 */
grid-auto-flow: row dense; /* 按行紧凑填充 */
}
dense 模式会尝试填补前面项目留下的空白,但可能导致视觉顺序与 DOM 顺序不一致。
grid-auto-rows 和 grid-auto-columns
定义隐式网格轨道的大小:
.container {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px; /* 自动创建的行高度为 100px */
grid-auto-rows: minmax(100px, auto); /* 最小 100px,最大自动 */
}
当项目超出显式定义的网格范围时,会自动创建隐式轨道。
常见布局模式
圣杯布局
.layout {
display: grid;
grid-template:
"header header header" 60px
"nav main aside" 1fr
"footer footer footer" 40px
/ 200px 1fr 150px;
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
响应式网格
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
自动适应屏幕宽度,每列最小 250px,自动调整列数。
等高列
.equal-height {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* 默认 align-items: stretch,项目自动等高 */
}
Grid 默认拉伸项目填满行高,实现等高列。
堆叠效果
.stack {
display: grid;
}
.stack > * {
grid-area: 1 / 1; /* 所有项目放在同一单元格 */
}
所有项目叠加在同一位置,可以创建层叠效果或切换可见性实现轮播。
12 列网格系统
.grid-12 {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 20px;
}
.col-6 { grid-column: span 6; }
.col-4 { grid-column: span 4; }
.col-3 { grid-column: span 3; }
.col-8 { grid-column: span 8; }
<div class="grid-12">
<div class="col-8">占 8 列</div>
<div class="col-4">占 4 列</div>
</div>
Grid 与 Flexbox 的选择
两种布局各有优势,选择原则:
使用 Grid 的场景:
- 二维布局(同时控制行和列)
- 页面整体结构
- 复杂的网格对齐
- 需要精确控制项目位置
使用 Flexbox 的场景:
- 一维布局(单行或单列)
- 组件内部布局
- 内容对齐和分布
- 动态数量项目的排列
结合使用:
/* 页面结构用 Grid */
.page {
display: grid;
grid-template:
"header header" auto
"nav main" 1fr
"footer footer" auto
/ 200px 1fr;
}
/* 组件内部用 Flexbox */
.nav {
display: flex;
flex-direction: column;
gap: 10px;
}
小结
这一章我们学习了:
- Grid 布局的基本概念:容器、项目、网格线、轨道、单元格、区域
- 定义网格:grid-template-columns、grid-template-rows、grid-template-areas
- fr 单位和 minmax()、repeat() 函数
- 项目放置:基于网格线、基于区域
- 对齐方式:justify-items、align-items、justify-content、align-content
- 自动布局:grid-auto-flow、grid-auto-rows
- 常见布局模式
Grid 是强大的二维布局工具,与 Flexbox 配合使用可以应对几乎所有布局需求。记住几个关键点:
repeat(auto-fit, minmax(最小值, 1fr))实现响应式网格grid-template-areas让布局更直观grid-column: 1 / -1让项目跨越整行- Grid 默认实现等高列
下一章我们将学习 CSS 定位,了解如何精确控制元素在页面中的位置。