CSS Grid 布局完全指南

CSS Grid 基础概念

CSS Grid 是CSS中最强大的布局系统之一,它是一个二维布局系统,可以同时处理行和列。与Flexbox(一维布局)不同,Grid可以创建复杂的网格布局,非常适合构建现代网页界面。

Grid容器和Grid项目

要使用Grid布局,首先需要将一个元素定义为Grid容器,其子元素自动成为Grid项目。

/* 定义Grid容器 */
.grid-container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr; /* 三列 */
    grid-template-rows: 100px 200px;    /* 两行 */
    gap: 20px; /* 行列间距 */
}

/* HTML结构 */
<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 class="item">5</div>
    <div class="item">6</div>
</div>

基本术语

  • Grid容器:应用 display: grid 的元素
  • Grid项目:Grid容器的直接子元素
  • Grid线:划分网格的线,包括垂直的列线和水平的行线
  • Grid轨道:两条相邻Grid线之间的空间(行或列)
  • Grid单元格:四条Grid线包围的最小单位
  • Grid区域:任意数量的相邻Grid单元格组成的矩形区域

Grid容器属性

1. 定义网格轨道

.container {
    display: grid;
    
    /* 定义列 */
    grid-template-columns: 100px 1fr 2fr;
    /* 或者使用 repeat() 函数 */
    grid-template-columns: repeat(3, 1fr);
    
    /* 定义行 */
    grid-template-rows: 100px auto 200px;
    
    /* 定义行和列的简写 */
    grid-template: 100px auto 200px / 1fr 2fr 1fr;
}

2. 网格间距

.container {
    /* 行列间距相同 */
    gap: 20px;
    
    /* 分别设置行列间距 */
    column-gap: 10px;
    row-gap: 20px;
}

3. 对齐方式

.container {
    /* 主轴对齐(水平) */
    justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
    
    /* 交叉轴对齐(垂直) */
    align-content: start | end | center | stretch | space-around | space-between | space-evenly;
    
    /* 项目在单元格内的对齐 */
    justify-items: start | end | center | stretch;
    align-items: start | end | center | stretch;
}

Grid项目属性

1. 项目位置

.item {
    /* 通过网格线定位 */
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 1;
    grid-row-end: 2;
    
    /* 简写 */
    grid-column: 1 / 3;  /* 等价于 grid-column-start: 1; grid-column-end: 3; */
    grid-row: 1 / 2;
    
    /* 使用span关键字 */
    grid-column: 1 / span 2;  /* 从第1列开始,跨越2列 */
    grid-row: span 2;         /* 跨越2行 */
}

2. 网格区域

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

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

3. 项目对齐

.item {
    /* 覆盖容器的对齐方式 */
    justify-self: start | end | center | stretch;
    align-self: start | end | center | stretch;
    
    /* 简写 */
    place-self: center stretch; /* align-self justify-self */
}

高级Grid技巧

1. 隐式网格和自动放置

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    
    /* 控制自动放置算法 */
    grid-auto-flow: row; /* 默认,按行填充 */
    grid-auto-flow: column; /* 按列填充 */
    grid-auto-flow: dense; /* 密集填充,尝试填充空白 */
    
    /* 定义隐式网格轨道大小 */
    grid-auto-rows: 100px;
    grid-auto-columns: 1fr;
}

2. 响应式网格布局

.container {
    display: grid;
    
    /* 使用minmax()和auto-fit创建响应式网格 */
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    
    /* 或者使用auto-fill */
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

/* auto-fit vs auto-fill */
/* auto-fit: 拉伸可用项目填充容器 */
/* auto-fill: 创建尽可能多的轨道,即使没有项目填充 */

3. 复杂网格布局示例

/* 现代网页布局 */
.layout {
    display: grid;
    grid-template-columns: 250px 1fr 300px;
    grid-template-rows: 80px 1fr 100px;
    min-height: 100vh;
    grid-template-areas:
        "header header header"
        "sidebar main aside"
        "footer footer footer";
    gap: 20px;
}

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

/* 响应式调整 */
@media (max-width: 1024px) {
    .layout {
        grid-template-columns: 200px 1fr;
        grid-template-rows: 80px auto auto 100px;
        grid-template-areas:
            "header header"
            "sidebar main"
            "aside aside"
            "footer footer";
    }
}

@media (max-width: 768px) {
    .layout {
        grid-template-columns: 1fr;
        grid-template-rows: 60px auto auto auto 80px;
        grid-template-areas:
            "header"
            "sidebar"
            "main"
            "aside"
            "footer";
    }
}

4. 子网格(Subgrid)

CSS Grid Level 2 引入了子网格功能,允许嵌套的网格与父网格对齐。

.parent {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: auto 1fr auto;
    gap: 20px;
}

.child {
    display: grid;
    grid-template-columns: subgrid; /* 继承父网格的列 */
    grid-template-rows: subgrid;     /* 继承父网格的行 */
    grid-column: span 2;            /* 跨越两列 */
}

实用示例:照片墙布局

.photo-wall {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    grid-auto-rows: 200px;
    gap: 15px;
    grid-auto-flow: dense; /* 启用密集填充 */
}

.photo {
    overflow: hidden;
    border-radius: 8px;
    position: relative;
}

/* 让一些照片更大 */
.photo:nth-child(2n) {
    grid-row: span 2;
}

.photo:nth-child(3n) {
    grid-column: span 2;
}

/* 响应式调整 */
@media (max-width: 768px) {
    .photo-wall {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
        grid-auto-rows: 150px;
    }
}

Grid布局最佳实践

  1. 渐进增强:为不支持Grid的浏览器提供回退方案
  2. 使用命名网格线:提高代码可读性
  3. 结合Flexbox使用:Grid用于整体布局,Flexbox用于组件内部布局
  4. 性能考虑:避免过度复杂的网格嵌套
  5. 测试不同浏览器:确保兼容性

CSS Grid是现代Web布局的强大工具,掌握它可以让您创建出以前需要复杂hack才能实现的布局。通过组合使用Grid的各种特性,您可以构建出灵活、响应式和可维护的网页布局。