Grid 网格布局:二维世界的布局王者,像下围棋一样掌控页面
还记得小时候玩的方格本吗?一行一行,一列一列,规规矩矩。Grid布局就是把这种“方格本”思维带到了CSS里。你可以在页面上画出任意行、任意列,然后把元素放进去,想放哪格放哪格,甚至可以合并单元格——就像Excel表格,但比Excel灵活一万倍。 Grid是CSS布局的终极武器,尤其适合做页面整体架构、卡片墙、仪表盘这类需要同时控制行和列的场景。如果说Flexbox是特种兵,擅长单兵作战,那Grid就是指挥官,能调动千军万马。 和Flexbox类似,Grid也是作用于父容器和直接子项目。只要在父元素上设置 默认情况下,网格只有一列,行高由内容决定。要真正“画”出网格,你需要用 你可以用各种单位定义行列的尺寸,比如像素、百分比、em等。 这样你就画了一个3列2行的网格,一共6个格子。项目会按顺序自动填充每个格子,就像表格里从左到右、从上到下填数据一样。 Grid引入了 如果父容器宽度是1200px,那么第一列占300px,第二列600px,第三列300px。 如果你要定义很多等宽的列,手动写很累。 有时候我们希望列宽能在一定范围内弹性变化,比如最小200px,最大自适应。 当列数不确定时,可以用 这段代码的意思是:每列最小200px,如果容器足够宽,就放尽可能多的列,并且每列等宽;当容器变窄时,列数自动减少,每列仍不小于200px。这就是纯CSS实现的响应式卡片墙! 每个网格都由网格线划分。比如3列有4条纵向网格线(从1开始编号),2行有3条横向网格线。你可以用这些线来精确放置项目。 简写为: 也可以从哪条线开始,并指定跨度: 网格线也可以命名,比如 如果你觉得用线编号不够直观,可以给网格区域命名。用 这个布局清晰得像图纸一样,每个区域的名字直接对应一个网格单元格。注意, 用 项目默认填满整个单元格,但你可以控制它们的位置。 如果想单独控制某个项目,用 如果网格的总尺寸小于容器,可以用 取值同样是 就这么简单,三栏就出来了,而且中间自适应。 我们希望卡片最小200px,尽量填满容器,而且自动换行。 无论容器多宽,卡片都会自动调整列数,完美响应式。 比如一个封面图占两列,下方三个卡片各占一列。 后台常有复杂区域划分,用 各区域对号入座,结构一目了然。 Grid还可以让多个元素重叠。通过给它们设置相同的网格区域,然后利用 很多人纠结什么时候用Grid,什么时候用Flexbox。其实很简单: 它们不是替代关系,而是配合关系。你可以在Grid单元格里用Flexbox排列内部元素,也可以把Flexbox项目里再嵌套Grid。两者结合,天下无敌。 如果只设置 如果项目数量超过网格单元格,会自动创建隐式网格(新行),行高默认 间隙是在分配fr之前扣除的。比如三列1fr,gap 20px,那么每列实际宽度 = (容器宽度 - 40px) / 3。所以计算时要考虑间隙。 这个容易搞错。不过可以用 Grid布局是CSS给前端开发者的一份大礼,它把网页布局变成了一种直观、可预测的体验。核心要点: Grid不难,关键是多动手画格子。一旦你习惯了这种“下围棋”式的布局思维,你会发现以前那些棘手的布局都变成了填空题。 如果你喜欢这篇文章,欢迎点赞、收藏、分享。明天我们将进入CSS另一个重要话题——响应式设计与移动端适配,教你如何一套代码搞定手机、平板、电脑。 明日预告:响应式设计的核心:媒体查询、流式布局、移动端适配,从零构建一个全端兼容的页面。如果说Flexbox是“一维战神”,擅长排排坐,那Grid就是“二维霸主”,能同时操控行和列。今天我们就来下这盘“布局围棋”,用网格思想彻底重构网页,让复杂布局变得像填格子一样简单。
前言
一、Grid的核心概念:容器与项目,行与列
display: grid或display: inline-grid,你就开启了一个网格世界。.container {
display: grid;
}grid-template-rows和grid-template-columns定义行和列。二、定义网格:画出你的棋盘
1. 固定行高和列宽
.container {
display: grid;
grid-template-columns: 200px 200px 200px; /* 三列,每列200px */
grid-template-rows: 100px 150px; /* 两行,第一行100px,第二行150px */
}2. fr单位:分蛋糕神器
fr单位(fraction的缩写),表示剩余空间的比例分配。这比Flexbox的flex-grow更直观。.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr; /* 三列,中间占两份,两边各占一份 */
}fr可以和固定单位混用,比如200px 1fr 2fr,浏览器会先分配200px,剩下的按比例分。3. repeat() 函数:偷懒必备
repeat()函数来救场。.container {
grid-template-columns: repeat(3, 1fr); /* 三列等宽,相当于 1fr 1fr 1fr */
grid-template-rows: repeat(4, 100px); /* 四行,每行100px */
}repeat()还可以组合不同模式,比如repeat(2, 100px 1fr)表示重复两次“100px 1fr”的序列,最终得到四列:100px、1fr、100px、1fr。4. minmax():给尺寸一个范围
minmax()搞定。.container {
grid-template-columns: minmax(200px, 1fr) 2fr; /* 第一列最小200px,可以放大到1fr,第二列固定2fr */
}5. auto-fill 与 auto-fit:响应式利器
auto-fill或auto-fit配合minmax实现类似“流动布局”的效果。auto-fill:尽可能多地填充列,即使某些列是空的。auto-fit:也是尽可能多地填充,但会把空列收缩为0,让有内容的列伸展。.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}三、网格线:定位的坐标系
.item {
grid-column-start: 1;
grid-column-end: 3; /* 从第1条纵向线跨到第3条线,即占据前两列 */
grid-row-start: 1;
grid-row-end: 3; /* 从第1条横向线跨到第3条线,即占据前两行 */
}.item {
grid-column: 1 / 3;
grid-row: 1 / 3;
}.item {
grid-column: 1 / span 2; /* 从第1列开始,跨2列,等同于1/3 */
grid-row: 1 / span 2;
}grid-template-columns: [main-start] 1fr [main-end],然后使用命名来定位。四、网格区域:给格子起名字
grid-template-areas属性来划分区域。.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 100px 1fr 100px;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
}
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.aside {
grid-area: aside;
}
.footer {
grid-area: footer;
}grid-template-areas里的每个单元格必须填满,不能有空洞;可以用.表示空单元格。五、间距与对齐:让网格透气
1. 行列间距
gap属性设置网格线之间的间距,可以分别设置行间距和列间距:.container {
gap: 20px; /* 行列间距都是20px */
row-gap: 10px; /* 单独设置行间距 */
column-gap: 15px; /* 单独设置列间距 */
}2. 项目在单元格内的对齐
justify-items:控制项目在单元格内水平方向的对齐(左中右)。align-items:控制项目在单元格内垂直方向的对齐(上中下)。start、end、center、stretch(默认)。.container {
justify-items: center; /* 所有项目水平居中 */
align-items: center; /* 所有项目垂直居中 */
}justify-self和align-self。3. 整个网格在容器内的对齐
justify-content和align-content控制网格整体的对齐,类似于Flexbox。.container {
justify-content: center; /* 网格整体水平居中 */
align-content: center; /* 网格整体垂直居中 */
}start、end、center、space-between、space-around、space-evenly。六、实战:用Grid搭建常见布局
1. 经典三栏布局(圣杯)
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
gap: 20px;
}2. 响应式卡片墙
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}3. 不规则布局:杂志风格
<div class="magazine">
<div class="feature">封面大图</div>
<div class="card">卡片1</div>
<div class="card">卡片2</div>
<div class="card">卡片3</div>
</div>.magazine {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.feature {
grid-column: 1 / -1; /* 从第一列线到最后一列线,即占满整行 */
}-1表示最后一条网格线,很方便。4. 后台管理仪表盘
grid-template-areas最合适。.dashboard {
display: grid;
grid-template-columns: 250px 1fr 300px;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header header"
"sidebar main widgets"
"footer footer footer";
height: 100vh;
}5. 叠加效果
z-index控制层级。.container {
display: grid;
grid-template-columns: 1fr 1fr;
}
.item1 {
grid-area: 1 / 1 / 2 / 3; /* 占满整行 */
background: red;
z-index: 1;
}
.item2 {
grid-area: 1 / 2 / 2 / 3; /* 只占第二列 */
background: blue;
opacity: 0.5;
z-index: 2; /* 显示在上层 */
}七、Grid vs Flexbox:怎么选?
八、常见坑点与避坑指南
1. 默认不是严格的一行一列
display: grid而不定义行列,默认只有一列,行数由项目数量决定(每个项目占一行)。所以一定要定义行列。2. 项目会自动填充,但可能超出网格
auto。你可以用grid-auto-rows控制隐式行的高度。.container {
grid-auto-rows: 100px; /* 隐式创建的行高100px */
}3. fr 和 minmax 结合时注意死循环
minmax(200px, 1fr)的意思是:优先让列宽为1fr,但不会小于200px。这通常没问题,但如果你把所有列都设成这样,且容器总宽度小于列数*200px,就会出现溢出(因为每列都强制不小于200px)。这时可以改用auto-fit和minmax的巧妙组合,或者用max-width限制。4. gap 会占用 fr 空间
5. 网格线编号从1开始,不是0
-1表示最后一条线,比较方便。九、总结
grid-template-columns和grid-template-rows定义网格结构。fr、repeat()、minmax()灵活控制尺寸。grid-column/grid-row或grid-area放置项目。gap控制间距,用justify/align控制对齐。auto-fit和minmax实现响应式。grid-template-areas命名,代码如设计图。