CSS:Grid 二维布局
编辑文章简介
CSS Grid布局是一个用于在网页上创建二维(行和列)布局系统的强大工具,它让你能像设计师一样轻松地划分区域、排列元素,是构建现代复杂网页界面的核心CSS模块。
语法
Grid布局通过为父容器(网格容器)和其子项(网格项目)设置一系列属性来工作。
容器属性
.grid-container {
display: grid | inline-grid; /* 开启网格布局 */
grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
grid-template-areas: "<grid-area-name> ..." "...";
grid-gap: <grid-row-gap> <grid-column-gap>; /* 旧语法,请使用 gap */
gap: <row-gap> <column-gap>; /* 现代标准 */
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
grid-auto-columns: <track-size>;
grid-auto-rows: <track-size>;
grid-auto-flow: row | column | row dense | column dense;
}
/* <track-size> 可以是:长度(px, %)、fr单位、minmax(min, max)、auto */
/* <grid-area-name> 是为网格区域定义的名称 */
子项属性
.grid-item {
grid-column-start: <number> | <name> | span <number> | span <name> | auto;
grid-column-end: <number> | <name> | span <number> | span <name> | auto;
grid-row-start: <number> | <name> | span <number> | span <name> | auto;
grid-row-end: <number> | <name> | span <number> | span <name> | auto;
/* 简写属性 */
grid-column: <start-line> / <end-line>;
grid-row: <start-line> / <end-line>;
grid-area: <row-start> / <column-start> / <row-end> / <column-end> | <area-name>;
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
}
用法
基础用法
最基础的用法是定义一个固定列数和行数的网格,并将子项放置其中。
<!-- HTML结构:一个容器和若干子项 -->
<div class="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
</div>
/* 在CSS文件中定义网格 */
.container {
display: grid; /* 1. 声明为网格容器 */
grid-template-columns: 100px 100px 100px; /* 2. 定义三列,每列100px宽 */
grid-template-rows: 50px 50px; /* 3. 定义两行,每行50px高 */
gap: 10px; /* 4. 设置行和列之间的间隙为10px */
background-color: #f0f0f0;
padding: 10px;
}
.item {
background-color: #4CAF50;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
这个例子创建了一个简单的3×2网格。子项会按照HTML中的顺序,从左到右、从上到下自动填充到每个网格单元格中。
进阶用法
1. 创建灵活的响应式布局
使用 fr 单位、minmax() 和 repeat() 函数可以创建能自适应容器大小的布局。
.container {
display: grid;
/* 第一列最小200px,最大1份可用空间;第二列固定200px;第三列最小100px */
grid-template-columns: minmax(200px, 1fr) 200px minmax(100px, 300px);
/* 行高自动,但最小100px */
grid-auto-rows: minmax(100px, auto);
gap: 15px;
}
2. 使用命名区域进行直观布局
通过 grid-template-areas 可以像画草图一样定义布局,非常直观。
.container {
display: grid;
grid-template-columns: 1fr 3fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 0; /* 此布局可能不需要间隙 */
min-height: 100vh;
}
.item-header { grid-area: header; background: #8a2be2; }
.item-sidebar { grid-area: sidebar; background: #ff7f50; }
.item-main { grid-area: main; background: #6495ed; }
.item-footer { grid-area: footer; background: #3cb371; }
<div class="container">
<div class="item item-header">Header</div>
<div class="item item-sidebar">Sidebar</div>
<div class="item item-main">Main Content</div>
<div class="item item-footer">Footer</div>
</div>
3. 基于网格线的精准定位
可以精确控制一个子项占据哪几条网格线之间的区域。
.item-1 {
/* 从第1条列线开始,跨越到第3条列线(即占据前两列) */
/* 从第1条行线开始,跨越到第3条行线(即占据前两行) */
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.item-2 {
/* 从第2条列线开始,跨越2列 */
/* 从第3条行线开始,到第4条行线结束 */
grid-column: 2 / span 2;
grid-row: 3 / 4;
}
易错点
1. 混淆 Grid 与 Flexbox 的适用场景
- 错误理解:用Flexbox去做整体的页面二维布局,或者用Grid去处理简单的单行/列对齐。
- 核心区别:
- Flexbox 是一维布局,专为单行或单列的内容分发和对齐设计。适合组件内部、导航栏、弹性列表等。
- Grid 是二维布局,同时控制行和列。适合整个页面的宏观布局、卡片网格、仪表盘等。
- 示例:一个产品卡片列表,如果只是水平排列并自动换行,用Flexbox。如果需要严格对齐到行和列的网格线上,用Grid。
2. 过度依赖网格线编号
- 错误示例:
/* 当网格结构改变时,这些数字需要全部重新计算 */ .item { grid-column: 3 / 5; } - 正确做法:尽可能使用命名网格线或命名区域。
.container { grid-template-columns: [start] 1fr [content-start] 3fr [content-end] 1fr [end]; } .item { grid-column: content-start / content-end; } /* 清晰且稳定 */
3. 忽略隐式网格的样式
当项目数量超过 grid-template-rows/columns 定义的范围时,浏览器会自动创建新的行/列(隐式网格)。如果未定义其尺寸,可能导致布局混乱。
– 错误示例:
“`css
.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 只定义了3列 */
grid-template-rows: 100px 100px; /* 只定义了两行 */
}
/* 当有第7个项目时,它会跑到第三行,但行高是默认的`auto`,可能很矮 */
“`
– **正确做法**:使用 `grid-auto-rows` 和 `grid-auto-columns` 设置隐式网格的尺寸。
“`css
.container {
/* … 其他定义 … */
grid-auto-rows: 150px; /* 所有额外创建的行都高150px */
}
“`
最佳实践
使用命名线和区域提升可读性
如上文易错点2所示,为网格线和区域赋予有语义的名称,能极大提升CSS代码的可读性和可维护性。你的布局意图会直接从代码中体现出来,而不是隐藏在抽象的数字背后。
.page {
display: grid;
grid-template-columns:
[full-start] minmax(1em, 1fr)
[main-start] minmax(0, 70rem) [main-end]
minmax(1em, 1fr) [full-end];
}
.content {
/* 一目了然:内容从主区域开始到主区域结束 */
grid-column: main-start / main-end;
}
在容器上定义布局,子项仅做微调
Grid的核心思想是“容器驱动布局”。应将绝大部分布局逻辑(定义轨道、区域)写在容器的CSS规则中。子项的属性(grid-column, grid-row)只应用于那些需要特殊定位或跨度的个别项目。这符合“关注点分离”原则,使布局更易于理解和整体修改。
利用 minmax() 和 auto-fill/auto-fit 实现真正的响应式
对于需要自适应列数的布局(如相册、产品网格),避免编写多个媒体查询。使用 repeat() 配合 auto-fill/auto-fit 和 minmax()。
.container {
display: grid;
/* 在至少200px宽的前提下,尽可能多地填充列 */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
auto-fill:尽可能多地创建轨道,即使它们当前是空的(为未来元素留出空间)。auto-fit:伸展当前已有的项目以填满可用空间。
使用 gap 而非 margin 控制间距
Grid布局中的 gap 属性是专门用来设置网格线之间间距的。相比于在子项上设置 margin,gap 有显著优势:
– 更简洁:只需在容器上设置一次。
– 更可控:间隙只出现在网格线之间,而不会在容器边缘产生多余间距。
– 无副作用:避免了 margin 折叠等经典CSS问题。