CSS Grid — 网格布局

2024/11/17

Grid 是一种二维布局系统,既能控制行(row)又能控制列(column),相比Flex布局更适合做卡片布局以及响应式栅格系统。

一、基本语法

1.设置网格容器

display: grid;

2.设置列

fr单位:是Grid布局中专用的分数单位,用于按比例分配网格容器中的可用空间

<div class="container">
  <div>A</div>
  <div>B</div>
  <div>C</div>
  <div>D</div>
 </div>
<style>
    .container {
        display: grid;
        /* 设置每行3列,第1列宽度固定为100px,第2列占剩余宽度的1/3,第3列占剩余宽度的2/3 */
        grid-template-columns: 100px 1fr 2fr;
        gap: 20px;
        div {
            height: 200px;
            background-color: #fffacd;
            border-radius: 10px;
        }
    }
</style>

repeat()函数:是Grid布局中的工具函数,用于重复创建相同模式的网格轨道,减少重复代码。

// 设置5列自适应的网格
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;

// 等价于
grid-template-columns: repeat(5, 1fr);
auto-fill参数:尽可能多地创建轨道(即使空轨道也会保留空间)
// 自动填充尽可能多的150px宽的列
grid-template-columns: repeat(auto-fill, 150px);

3.设置行

<div class="container">
    <div>A</div>
    <div>B</div>
    <div>C</div>
    <div>
        <div>D1</div>
        <div>D2</div>
        <div>D3</div>
    </div>
</div>
<style>
    body {
    margin: 0;
    font-size: 30px;
    }
    .container {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        /* 第1行高度固定为50px,第2行自动调整根据内容撑开 */
        grid-template-rows: 50px auto;
        gap: 20px;
        div {
            background-color: #fffacd;
            border-radius: 10px;
        }
    }
</style>

4.控制某个网格的位置

想让某个网格跨行跨列展示,可以使用grid-column、grid-row设置网格线的范围来控制。

<div class="container">
    <div class="box">A</div>
    <div>B</div>
    <div>C</div>
    <div>D</div>
    <div>E</div>
    <div>F</div>
    <div>G</div>
    <div>H</div>
    <div>I</div>
    <div>J</div>
    <div>K</div>
</div>
<style>
    .container {
        padding: 20px;
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 20px;
        div {
            height: 100px;
            background-color: #fffacd;
            border-radius: 10px;
        }
        .box {
            /* 设置列的内容范围从第1条网格线开始到第3条网格线结束 */
            grid-column: 1 / 3;
            /* 设置行的内容范围从第2条网格线开始到第4条网格线结束, */
            grid-row: 2 / 4;
            height: 100%;
            background-color: #fff0f5;
        }
    }
</style>

5.设置行与列之间的间隙

// 设置网格之间的间距
gap:20px;

// 等价于
row-gap: 10px;
column-gap: 10px;

6.响应式布局

minmax()函数:定义网格轨道的尺寸范围,使布局更灵活

auto-fit参数:自动填充尽可能多的列

<div class="container">
    <div>A</div>
    <div>B</div>
    <div>C</div>
    <div>D</div>
    <div>E</div>
    <div>F</div>
    <div>G</div>
    <div>H</div>
    <div>I</div>
    <div>J</div>
    <div>K</div>
</div>
<style>
    .container {
        padding: 20px;
        display: grid;
        /* 每列最小宽度为100px,最多占满剩余空间,填充尽可能多的列 */
        grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
        gap: 20px;
        div {
            height: 100px;
            background-color: #fffacd;
            border-radius: 10px;
        }
    }
</style>

二、兼容性

需要注意grid、gap的兼容性:

兼容性gap支持建议用法
Flex✅ 极好⚠️ Safari 14.1+ 才支持 gap一维布局最佳选择
Grid✅ iOS11+ 安全使用✅ Safari 10.1+ 才支持二维/响应式布局推荐
gap in Flex❌ iOS14以下无效,IE11不支持保守使用,推荐用 margin

下面是一个响应式网格卡片布局示例,旧版不支持 Grid 时自动回退到Flex,兼容 ios10+

<div class="container">
    <div>A</div>
    <div>B</div>
    <div>C</div>
    <div>D</div>
    <div>E</div>
    <div>F</div>
    <div>G</div>
    <div>H</div>
    <div>I</div>
    <div>J</div>
    <div>K</div>
</div>
<style>
    .container {
        padding: 20px;
        display: flex;
        flex-wrap: wrap;
        margin: -10px;
        div {
            width: 100px;
            height: 100px;
            margin: 10px;
            background-color: #fffacd;
            border-radius: 10px;
        }
    }

    /* 检测支持 Grid 时启用 Grid 布局 */
    @supports (display: grid) {
        .container {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
            gap: 20px;
            margin: 0;
            div {
                width: auto;
                margin: 0;
            }
        }
    }
</style>