二、Grid 基础概念
2.1 基本术语
┌─────────────────────────────────┐
│ Grid Container(网格容器) │
│ ┌─────┬─────┬─────┬─────┐ │
│ │ A │ B │ C │ D │ │ ← Grid Track(行)
│ ├─────┼─────┼─────┼─────┤ │
│ │ E │ F │ G │ H │ │
│ ├─────┼─────┼─────┼─────┤ │
│ └─────┴─────┴─────┴─────┘ │
│ ↑ │
│ Grid Track(列) │
└─────────────────────────────────┘
- Grid Container:应用
display: grid的元素 - Grid Item:容器的直接子元素
- Grid Line:划分网格的线
- Grid Track:两条相邻网格线之间的空间(行或列)
- Grid Cell:两条相邻行和列交叉形成的单元格
- Grid Area:一个或多个单元格组成的区域
2.2 创建第一个 Grid 布局
<div class="grid-container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
.grid-container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px;
gap: 10px;
}
.item {
background: #4CAF50;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
}
三、Grid 容器属性
3.1 grid-template-columns 与 grid-template-rows
定义网格的列和行:
.grid-container {
/* 像素 */
grid-template-columns: 100px 100px 100px;
/* 百分比 */
grid-template-columns: 33.33% 33.33% 33.33%;
/* fr 单位(fraction,比例) */
grid-template-columns: 1fr 1fr 1fr;
/* 混合单位 */
grid-template-columns: 200px 1fr 2fr;
/* repeat() 函数 */
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(3, 100px 200px);
/* auto-fill 自动填充 */
grid-template-columns: repeat(auto-fill, 100px);
/* auto-fit 自适应 */
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
3.2 gap(间距)
.grid-container {
/* 旧写法 */
grid-gap: 10px;
grid-column-gap: 10px;
grid-row-gap: 10px;
/* 新写法(推荐) */
gap: 10px;
column-gap: 10px;
row-gap: 10px;
/* 分别设置行间距和列间距 */
gap: 10px 20px; /* row column */
}
3.3 grid-template-areas 命名区域
.grid-container {
grid-template-areas:
"header header header"
"sidebar content content"
"footer footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
3.4 justify-items 与 align-items
对齐网格项在单元格内的对齐方式:
.grid-container {
/* 水平对齐 */
justify-items: start | end | center | stretch;
/* 垂直对齐 */
align-items: start | end | center | stretch;
/* 简写 */
place-items: center center;
}
3.5 justify-content 与 align-content
对齐整个网格内容:
.grid-container {
/* 水平对齐 */
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
/* 垂直对齐 */
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
/* 简写 */
place-content: center center;
}
3.6 grid-auto-columns 与 grid-auto-rows
定义自动创建的轨道大小:
.grid-container {
grid-auto-rows: 100px;
grid-auto-columns: 100px;
}
3.7 grid-auto-flow 控制自动放置
.grid-container {
/* 先行后列 */
grid-auto-flow: row;
/* 先列后行 */
grid-auto-flow: column;
/* 密集填充 */
grid-auto-flow: dense;
}
四、Grid 项目属性
4.1 grid-column 与 grid-row 定位项目
.item {
/* 简写 */
grid-column: 1 / 3; /* 从第 1 列线到第 3 列线 */
grid-row: 1 / 2; /* 从第 1 行线到第 2 行线 */
/* 完整写法 */
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
/* 使用 span */
grid-column: 1 / span 2; /* 跨越 2 列 */
grid-row: span 1; /* 跨越 1 行 */
/* 只指定一端,另一端自动 */
grid-column: 2; /* 从第 2 列开始,跨越 1 列 */
}
4.2 grid-area 使用命名区域
.item {
grid-area: header; /* 使用命名区域 */
/* 或者用线位置 */
grid-area: 1 / 1 / 2 / 4; /* row-start / column-start / row-end / column-end */
}
4.3 justify-self 与 align-self
单个项目在单元格内的对齐:
.item {
/* 水平对齐 */
justify-self: start | end | center | stretch;
/* 垂直对齐 */
align-self: start | end | center | stretch;
/* 简写 */
place-self: center center;
}
4.4 order 控制项目顺序
.item:nth-child(1) { order: 3; }
.item:nth-child(2) { order: 1; }
.item:nth-child(3) { order: 2; }
五、实用函数与单位
5.1 fr 单位详解
fr(fraction)是 Grid 特有的单位,表示可用空间的比例:
.grid-container {
/* 三等分 */
grid-template-columns: 1fr 1fr 1fr;
/* 1:2 的比例 */
grid-template-columns: 1fr 2fr;
/* 固定宽度 + 比例 */
grid-template-columns: 200px 1fr 2fr;
}
5.2 repeat() 函数
.grid-container {
/* 重复 3 次 1fr */
grid-template-columns: repeat(3, 1fr);
/* 重复模式 */
grid-template-columns: repeat(2, 100px 200px);
/* 结合 minmax() */
grid-template-columns: repeat(3, minmax(100px, 1fr));
/* auto-fill */
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
/* auto-fit */
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
5.3 minmax() 函数
.grid-container {
/* 最小 100px,最大 1fr */
grid-template-columns: minmax(100px, 1fr) 1fr 1fr;
/* 结合 repeat() */
grid-template-columns: repeat(3, minmax(100px, 1fr));
}
5.4 min()、max()、clamp() 函数
.grid-container {
grid-template-columns: min(200px, 30%) 1fr 1fr;
grid-template-columns: max(150px, 20%) 1fr 1fr;
grid-template-columns: clamp(100px, 25%, 300px) 1fr 1fr;
}
六、响应式 Grid 布局
6.1 使用 auto-fit 和 minmax()
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
这会自动创建响应式布局,列数根据容器宽度自动调整。
6.2 媒体查询调整 Grid
/* 默认:1 列 */
.grid-container {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
/* 平板:2 列 */
@media (min-width: 768px) {
.grid-container {
grid-template-columns: 1fr 1fr;
}
}
/* 桌面:3 列 */
@media (min-width: 1024px) {
.grid-container {
grid-template-columns: 1fr 1fr 1fr;
}
}
/* 大屏:4 列 */
@media (min-width: 1440px) {
.grid-container {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
6.3 使用命名区域的响应式布局
.grid-container {
display: grid;
gap: 20px;
grid-template-areas:
"header"
"sidebar"
"content"
"footer";
}
@media (min-width: 768px) {
.grid-container {
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
}
七、深入理解 Grid 布局算法
7.1 轨道尺寸计算
Grid 计算轨道尺寸的过程:
// 简化的计算流程
function calculateGridTracks(container) {
const { gridTemplateColumns, gap, availableWidth } = container;
// 1. 处理固定尺寸
// 2. 处理百分比
// 3. 分配 fr 单位
return computedTracks;
}
7.2 自动放置算法
Grid 的自动放置有两种策略:
/* row - 先行后列(默认) */
.grid-container {
grid-auto-flow: row;
}
/* column - 先列后行 */
.grid-container {
grid-auto-flow: column;
}
/* dense - 密集填充,不留空隙 */
.grid-container {
grid-auto-flow: dense;
}
7.3 隐式网格
当项目位置超出显式定义的网格时,会创建隐式网格:
.grid-container {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 100px;
/* 定义隐式网格 */
grid-auto-rows: 80px;
grid-auto-columns: 100px;
}
八、实战案例
8.1 经典 Holy Grail 布局
<div class="holy-grail">
<header>Header</header>
<nav>Navigation</nav>
<main>Main Content</main>
<aside>Sidebar</aside>
<footer>Footer</footer>
</div>
.holy-grail {
display: grid;
min-height: 100vh;
grid-template:
"header header header" auto
"nav main aside" 1fr
"footer footer footer" auto /
200px 1fr 200px;
gap: 10px;
}
header { grid-area: header; background: #333; color: white; }
nav { grid-area: nav; background: #ddd; }
main { grid-area: main; background: #f5f5f5; }
aside { grid-area: aside; background: #ddd; }
footer { grid-area: footer; background: #333; color: white; }
8.2 卡片网格布局
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
padding: 2rem;
}
.card {
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.card-image {
height: 200px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.card-content {
padding: 1.5rem;
}
8.3 瀑布流布局(Masonry)
.masonry {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
grid-auto-rows: 10px;
}
.masonry-item {
margin-bottom: 1rem;
}
/* 不同高度的项目 */
.masonry-item:nth-child(3n+1) { grid-row: span 20; }
.masonry-item:nth-child(3n+2) { grid-row: span 25; }
.masonry-item:nth-child(3n) { grid-row: span 15; }
九、Grid 与 Flexbox 配合使用
9.1 何时使用 Grid,何时使用 Flexbox
/* Grid 适用于: */
/* - 页面整体布局
/* - 二维布局(同时控制行和列 */
/* - 需要精确控制位置 */
/* Flexbox 适用于: */
/* - 组件内部布局 */
/* - 一维布局(行或列) */
/* - 内容优先的布局 */
9.2 组合使用示例
/* Grid 作为外层布局 */
.page-layout {
display: grid;
grid-template-columns: 250px 1fr;
gap: 20px;
}
/* Flexbox 作为内部组件布局 */
.nav-menu {
display: flex;
flex-direction: column;
gap: 10px;
}
.card-list {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
十、性能优化与最佳实践
10.1 性能优化建议
/* 使用 grid-template 简写 */
.grid-container {
/* 不推荐:分开写 */
grid-template-columns: 1fr 1fr;
grid-template-rows: auto 1fr;
grid-template-areas: "header header" "main sidebar";
/* 推荐:简写 */
grid-template:
"header header" auto
"main sidebar" 1fr /
1fr 1fr;
}
10.2 最佳实践
- 使用
fr单位代替百分比 - 利用
auto-fit+minmax()做响应式 - 使用命名区域提高可读性
- 合理使用
gap代替margin - 与 Flexbox 配合使用