Grid布局

掌握CSS网格布局模型

什么是Grid布局?

CSS Grid布局是一个二维布局系统,专门用于处理行和列。它允许我们创建复杂的网页布局,比传统的布局方法更加直观和强大。Grid布局于2017年成为W3C标准,现已被所有现代浏览器支持。

Grid vs Flexbox:
  • Flexbox是一维布局(行或列)
  • Grid是二维布局(行和列)
  • Grid更适合整体页面布局
  • Flexbox更适合组件内的布局
  • 两者可以结合使用

Grid容器和Grid项目

要使用Grid布局,需要将一个容器元素设置为grid容器:

CSS
.container {
    display: grid;
}

容器内的直接子元素自动成为grid项目:

项目 1
项目 2
项目 3
项目 4
项目 5
项目 6

Grid容器属性

1. grid-template-columns 和 grid-template-rows

定义网格的列和行:

CSS
.container {
    display: grid;
    grid-template-columns: 100px 200px 100px;
    grid-template-rows: 100px 200px;
}

2. grid-template-areas

通过命名网格区域来定义布局:

CSS
.container {
    display: grid;
    grid-template-areas: 
        "header header header"
        "sidebar content content"
        "footer footer footer";
}

3. gap

定义网格项之间的间距:

CSS
.container {
    gap: 10px;
    /* 或者分别设置行和列间距 */
    row-gap: 10px;
    column-gap: 20px;
}

4. justify-items 和 align-items

定义网格项在单元格内的对齐方式:

CSS
.container {
    justify-items: start; /* 或 center, end, stretch */
    align-items: start; /* 或 center, end, stretch */
}

5. justify-content 和 align-content

定义整个网格在容器内的对齐方式:

CSS
.container {
    justify-content: center; /* 或 start, end, space-between, space-around, space-evenly */
    align-content: center; /* 或 start, end, space-between, space-around, space-evenly */
}

6. grid-auto-columns 和 grid-auto-rows

定义隐式网格轨道的大小:

CSS
.container {
    grid-auto-columns: 100px;
    grid-auto-rows: minmax(100px, auto);
}

7. grid-auto-flow

控制自动放置项目的算法:

CSS
.container {
    grid-auto-flow: row; /* 或 column, row dense, column dense */
}

Grid项目属性

1. grid-column 和 grid-row

定义项目在网格中的位置:

CSS
.item {
    grid-column: 1 / 3; /* 从第1条网格线到第3条网格线 */
    grid-row: 1; /* 只占用第1行 */
}

2. grid-area

通过名称或线号定义项目的位置:

CSS
.header {
    grid-area: header;
}

.sidebar {
    grid-area: sidebar;
}

3. justify-self 和 align-self

定义单个项目在单元格内的对齐方式:

CSS
.item {
    justify-self: center;
    align-self: center;
}

4. order

控制项目在网格中的显示顺序:

CSS
.item {
    order: 2; /* 数值越小,位置越靠前 */
}

fr单位和repeat()函数

fr单位

fr(fraction)单位表示网格容器中的可用空间的一部分:

CSS
.container {
    grid-template-columns: 1fr 2fr 1fr;
    /* 中间列是两侧列的两倍宽 */
}

repeat()函数

repeat()函数可以简化重复的模式:

CSS
.container {
    grid-template-columns: repeat(3, 1fr);
    /* 等同于 1fr 1fr 1fr */
    
    grid-template-columns: repeat(2, 100px 200px);
    /* 等同于 100px 200px 100px 200px */
}

minmax()函数

minmax()函数定义轨道大小的范围:

CSS
.container {
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    /* 自动填充,每列最小200px,最大1fr */
}

网格线命名

可以为网格线命名,使代码更易读:

CSS
.container {
    grid-template-columns: [start] 1fr [main-start] 2fr [main-end] 1fr [end];
    grid-template-rows: [top] 100px [content-top] auto [content-bottom] 100px [bottom];
}

.item {
    grid-column: main-start / main-end;
    grid-row: content-top / content-bottom;
}

Grid布局交互演示

当前布局: 3列 × 2行
项目数量: 6个项目
定义网格列的大小和数量
定义网格行的大小和数量
网格项之间的间距
整个网格在容器内的对齐
自动放置项目的算法
项目在单元格内的水平对齐
项目在单元格内的垂直对齐
1
项目 1
2
项目 2
3
项目 3
4
项目 4
5
项目 5
6
项目 6

生成的CSS代码

CSS
.grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 100px 100px;
  gap: 10px;
  justify-items: stretch;
  align-items: stretch;
  grid-auto-flow: row;
}

实际应用示例

经典网页布局

CSS
.page {
    display: grid;
    grid-template-areas: 
        "header header header"
        "nav main aside"
        "footer footer footer";
    grid-template-rows: auto 1fr auto;
    grid-template-columns: 200px 1fr 200px;
    min-height: 100vh;
}

.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }

响应式图片网格

CSS
.gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
}

表单布局

CSS
.form {
    display: grid;
    grid-template-columns: [labels] auto [controls] 1fr [info] auto;
    gap: 0.5rem 1rem;
}

.form label {
    grid-column: labels;
    align-self: center;
}

.form input {
    grid-column: controls;
}

浏览器支持与最佳实践

浏览器支持

CSS Grid布局在现代浏览器中得到广泛支持:

浏览器 版本 支持情况
Chrome 57+ 完全支持
Firefox 52+ 完全支持
Safari 10.1+ 完全支持
Edge 16+ 完全支持
IE 10-11 部分支持(旧语法)

渐进增强

对于不支持Grid的浏览器,可以使用Flexbox或传统布局作为回退方案:

CSS
/* 传统布局作为回退 */
.container {
    display: flex;
    flex-wrap: wrap;
}

@supports (display: grid) {
    .container {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    }
}

性能考虑

  • 避免过度嵌套Grid容器
  • 对于大量动态项目,考虑使用虚拟滚动
  • 使用will-change: transform优化动画性能