当然,除了 table 这种“老派”的布局方式,CSS 栅格布局还有很多现代且强大的实现途径。事实上,CSS Grid Layout 本身就是专门为解决这类二维布局问题而生的,它提供了一种比 table 更灵活、更语义化、也更易于维护的解决方案。
让我们抛开 table 不谈,深入聊聊 CSS Grid Layout 如何帮我们构建出你所说的这种栅格系统。
核心思想:定义网格,然后放置内容
CSS Grid Layout 的强大之处在于它允许你清晰地定义一个二维的网格系统,然后在这个网格中精确定位你的内容。你可以把它想象成在纸上先画好一条条横线和竖线,形成一个个方格,然后你再把你的文字、图片等内容放在你想要的那个方格里。
第一步:声明容器为 Grid 布局
你需要找到你想要作为“网格容器”的那个 HTML 元素,然后给它应用 `display: grid;`。这个操作就如同给这个元素施加了“魔法”,让它从此拥有了 grid 的能力,能够管理其内部的子元素(即“网格项”)的布局。
```html
```
```css
.gridcontainer {
display: grid; / 声明这是一个 grid 容器 /
/ 接下来我们就可以定义这个网格的结构了 /
}
```
第二步:定义网格的列和行
这是 Grid Layout 最核心的部分。你可以通过 `gridtemplatecolumns` 和 `gridtemplaterows` 来定义你的网格有多少列、多少行,以及每一列和每一行的宽度或高度。
`gridtemplatecolumns`: 定义网格的列。你可以指定列的数量和它们的宽度。
固定宽度: `gridtemplatecolumns: 100px 200px 50px;` 这会创建三列,宽度分别是 100px, 200px, 50px。
百分比宽度: `gridtemplatecolumns: 25% 50% 25%;` 这样三列的宽度会根据容器的宽度按比例分配。
`fr` 单位 (fractional unit): 这是 Grid Layout 中非常强大的一个单位。`fr` 代表“可用空间的一部分”。如果你有 `gridtemplatecolumns: 1fr 2fr 1fr;`,那么你的容器的总宽度会被分成 1+2+1 = 4 份,第一列占用 1 份,第二列占用 2 份,第三列占用 1 份。这使得响应式布局变得非常容易,因为列的宽度会根据容器的可用空间自动调整。
`repeat()` 函数: 当你有重复的列或行时,可以使用 `repeat()` 函数来简化代码,例如 `gridtemplatecolumns: repeat(3, 1fr);` 相当于 `gridtemplatecolumns: 1fr 1fr 1fr;`。
`auto` 关键字: `gridtemplatecolumns: auto 1fr auto;` 意思是中间的列会根据其内容自动调整宽度,而两边的列则会占据剩余的可用空间。
`gridtemplaterows`: 定义网格的行,用法与 `gridtemplatecolumns` 类似,只是它控制的是行的高度。
举个例子,创建一个等宽三列的栅格:
```css
.gridcontainer {
display: grid;
gridtemplatecolumns: 1fr 1fr 1fr; / 创建三列,每列占据相同的可用空间 /
gap: 20px; / 在列和行之间添加 20px 的间隙 /
}
```
第三步:在网格中放置内容
一旦你定义了网格的结构,下一步就是将你的 HTML 子元素(网格项)放到你想要的位置。
自动放置: 如果你不手动指定位置,Grid Layout 会按照它们在 HTML 中出现的顺序,自动将网格项填充到网格的单元格中。
手动放置: 你可以使用以下属性来精确控制网格项的位置:
`gridcolumnstart` 和 `gridcolumnend`: 指定一个网格项从哪一列的网格线开始,到哪一列的网格线结束。
`gridrowstart` 和 `gridrowend`: 指定一个网格项从哪一行开始,到哪一行结束。
简写属性 `gridcolumn` 和 `gridrow`: `gridcolumn: startline / endline;` 和 `gridrow: startline / endline;`。
跨越单元格: 你可以使用 `span` 关键字让一个网格项跨越多个单元格。例如,`gridcolumn: 1 / 4;` 意思是这个元素从第 1 列线开始,到第 4 列线结束(会跨越第 1、2、3 列)。`gridcolumn: 1 / span 2;` 意思是从第 1 列线开始,跨越 2 列。
举个例子,让第二个元素跨越两列:
```css
.gridcontainer {
display: grid;
gridtemplatecolumns: 1fr 1fr 1fr;
gap: 20px;
}
.griditem:nthchild(2) {
gridcolumn: 1 / 3; / 从第 1 列线开始,到第 3 列线结束,跨越两列 /
}
```
更高级的控制:网格模板区域 (Grid Template Areas)
如果你需要构建更复杂的、具有明确结构(例如页头、侧边栏、内容区、页脚)的布局,`gridtemplateareas` 是一个非常直观且强大的工具。
1. 给网格项命名:
```css
.header { gridarea: header; }
.sidebar { gridarea: sidebar; }
.content { gridarea: content; }
.footer { gridarea: footer; }
```
2. 在容器中定义布局:
```css
.gridcontainer {
display: grid;
gridtemplatecolumns: 1fr 3fr; / 两列布局 /
gridtemplaterows: auto 1fr auto; / 三行布局 /
gridtemplateareas:
"header header" / 第一行,header 元素占据两列 /
"sidebar content" / 第二行,sidebar 占据第一列,content 占据第二列 /
"footer footer"; / 第三行,footer 元素占据两列 /
gap: 10px;
}
```
通过这种方式,你可以在视觉上清晰地看到你的布局结构,并且通过改变 `gridtemplateareas` 的定义,可以非常方便地实现响应式布局的切换。例如,在小屏幕上,你可能希望所有内容都堆叠起来。
响应式设计与 Grid Layout
Grid Layout 与媒体查询(Media Queries)结合,能够实现极其精妙的响应式设计。你可以在不同屏幕尺寸下,重新定义 `gridtemplatecolumns`、`gridtemplaterows` 或 `gridtemplateareas`,从而轻松改变元素的排列方式。
```css
.gridcontainer {
display: grid;
gridtemplatecolumns: 1fr; / 默认是单列 /
gap: 10px;
}
@media (minwidth: 768px) {
.gridcontainer {
gridtemplatecolumns: 1fr 2fr 1fr; / 在屏幕宽度大于 768px 时,变成三列 /
}
}
```
对比 Table 布局的优势
语义化: Grid Layout 是专门为页面布局设计的,而 `
` 元素本意是用来展示表格数据的。使用 Grid Layout 可以使你的 HTML 更具语义,更容易理解。
灵活性: Grid Layout 提供了丰富的单位 (`fr`, `%`, `px`, `em`, `auto` 等) 和函数 (`repeat()`),可以创建出远比 Table 复杂的布局,并且调整起来更加方便。
易于维护: 改变布局结构(例如列数、排列顺序)时,Grid Layout 通常只需要修改少数几个 CSS 属性,而 Table 布局可能需要改动 HTML 结构。
响应式设计: Grid Layout 与媒体查询结合,可以轻松实现响应式布局,而 Table 布局在响应式设计方面就显得力不从心。
内容与结构分离: Grid Layout 让你能够完全在 CSS 中定义布局,而无需在 HTML 中通过 `colspan` 和 `rowspan` 来模拟布局,这使得 HTML 和 CSS 的分离更彻底。
总之,CSS Grid Layout 提供了一种现代、强大且灵活的方式来创建二维布局,它远远超越了 Table 布局在布局能力上的局限性。通过 `display: grid`、`gridtemplatecolumns`、`gridtemplaterows`、`gridarea` 等属性,你可以自由地设计出各种复杂的栅格系统,并且轻松实现响应式调整。