4. Grid网格布局基础:grid-template-columns、grid-template-rows、grid-gap、grid-area
说到CSS布局,Flexbox解决了一维排列的问题,但遇到二维布局——也就是同时控制行和列——就有点力不从心了。这时候,Grid网格布局就派上用场了。
我个人习惯把Grid想象成一张Excel表格。你定义好行和列,然后把元素往对应的单元格里一放,完事。听起来简单,但实际用起来,有几个核心属性你必须吃透。
4.1 网格容器与网格项目
先搞清楚两个概念:网格容器和网格项目。给一个元素设置 display: 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>
.grid-container {
display: grid;
}
嗯,这里要注意:只有直接子元素会成为网格项目。孙子元素不会自动参与网格布局。我在项目中遇到过有人把嵌套层级搞混,结果布局死活不对——其实就是忘了这个基本规则。
4.2 grid-template-columns 和 grid-template-rows
这两个属性是Grid布局的基石。它们分别定义列轨道和行轨道的数量与尺寸。
核心语法:
grid-template-columns: 值1 值2 ...;
grid-template-rows: 值1 值2 ...;
每个值代表一列或一行的宽度/高度。
举个例子,你想做一个三列等宽的布局:
.grid-container {
display: grid;
grid-template-columns: 200px 200px 200px;
grid-template-rows: 100px 100px;
}
这样会生成3列,每列200px宽;2行,每行100px高。一共6个单元格。
但实际项目中,固定像素用得少。我更推荐用fr单位——这是Grid特有的弹性单位,代表剩余空间的一份。
.grid-container {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
}
这段代码的意思是:把容器宽度分成4份,第一列占1份,第二列占2份,第三列占1份。说白了,就是比例分配。我在做后台管理系统时,经常用这种比例来布局侧边栏和主内容区。
还有几个常用写法:
repeat(3, 1fr)— 重复3次1fr,等价于1fr 1fr 1frauto— 由内容撑开minmax(100px, 1fr)— 最小100px,最大1fr弹性
我的小技巧:当你不知道有多少列时,可以用 auto-fill 或 auto-fit 配合 minmax 实现自适应网格。比如 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)),它会自动填充尽可能多的200px宽的列。
4.3 grid-gap(现称 gap)
网格项目之间需要间距,对吧?以前用 grid-gap,现在标准属性名改成了 gap。不过浏览器都兼容,你写哪个都行。
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px; /* 行和列间距都是20px */
/* 或者分开写 */
row-gap: 10px; /* 行间距 */
column-gap: 30px; /* 列间距 */
}
我曾经在项目里犯过一个低级错误:给网格容器设置了 margin 和 padding,但忘了加 gap,结果项目之间挤在一起,视觉上完全没层次感。加上 gap 后,整个页面瞬间清爽了。
注意:gap 只作用于网格项目之间,不会在网格容器边缘产生间距。如果你需要容器边缘也有间距,请使用 padding。
4.4 grid-area 与网格线
前面讲的都是自动排列。但有时候,你想让某个元素跨多列或多行,或者指定它放在某个特定位置。这时候就需要 grid-area 了。
先理解一个概念:网格线。每一条行和列的边界都是一条线,从1开始编号。比如一个3列2行的网格,有4条列网格线和3条行网格线。
.item1 {
grid-column: 1 / 3; /* 从第1条列线到第3条列线,即跨2列 */
grid-row: 1 / 2; /* 从第1条行线到第2条行线,即占1行 */
}
而 grid-area 是 grid-row-start、grid-column-start、grid-row-end、grid-column-end 的简写:
.item1 {
grid-area: 1 / 1 / 3 / 3;
/* 顺序:行起始 / 列起始 / 行结束 / 列结束 */
}
这段代码表示:从第1行第1列开始,到第3行第3列结束。说白了,就是占据左上角一个2x2的区域。
更优雅的方式是命名网格区域。你可以给每个区域起个名字,然后通过 grid-template-areas 来布局:
.grid-container {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 10px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
这样写,布局结构一目了然。我在做响应式设计时特别喜欢这种方式——只需要在媒体查询里重新定义 grid-template-areas,就能轻松改变整体布局。
避坑指南:命名区域时,每个单元格必须填一个名字,不能留空。如果你想让某个单元格空着,用 . 表示。比如 "header . sidebar" 表示中间那列空着。
4.5 知识体系总览
下面这张图帮你理清Grid网格布局的核心脉络:
4.6 实战:一个简单的页面骨架
把上面学到的知识串起来,写一个典型的页面布局:
<div class="page">
<header>头部</header>
<nav>导航</nav>
<main>主要内容</main>
<aside>侧边栏</aside>
<footer>底部</footer>
</div>
.page {
display: grid;
grid-template-columns: 200px 1fr 250px;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
gap: 15px;
height: 100vh;
}
header { grid-area: header; background: #4a90d9; }
nav { grid-area: nav; background: #f0f4f8; }
main { grid-area: main; background: #ffffff; }
aside { grid-area: aside; background: #f0f4f8; }
footer { grid-area: footer; background: #2c3e50; color: white; }
这段代码创建了一个经典的三栏布局:顶部通栏头部,左侧导航,中间主内容,右侧侧边栏,底部通栏页脚。而且通过 grid-template-areas,你一眼就能看出布局结构——比用浮动或定位清晰多了。
我的经验:在做响应式时,我通常会在 @media (max-width: 768px) 里把 grid-template-columns 改成 1fr,然后重新定义 grid-template-areas 让所有区域堆叠成一列。这样改起来非常快,而且不容易出错。
好了,Grid网格布局的基础就这些。你想想看,掌握了 grid-template-columns、grid-template-rows、gap 和 grid-area,你已经能搞定绝大多数二维布局场景了。剩下的就是多练,把命名区域和网格线的感觉找出来。
可可精品资料库