前端必学的 CSS Grid 布局体系

Grid Container(容器)

1. 定义网格

1.1 指定一个容器为网格布局

css 复制代码
display:grid/inline-grid

1.2 定义行和列

css 复制代码
 .container {
        width: 100vw;
        height: 100vh;
        display: grid;
        /* 一个两列,四行的网格布局 */
        grid-template-columns: 100px 100px;
        grid-template-rows: 100px 100px 100px 100px;
        .item {
          background-color: green;
          color: #fff;
        }
      }

💡 除了使用绝对单位,还可以使用百分比。

1.3 grid-template-areas

grid-template-areas用来通过命名区域的方式定义网格布局 ,让代码更直观。需要 grid-area 配合使用

  • 基本语法
    • 每一个单词代表一个单元格,单词之间用空格隔开。
    • 相同的单词会合并成一个区域
css 复制代码
.container {
        width: 100vw;
        height: 100vh;
        display: grid;
        grid-template-columns: 15% 80%;
        grid-template-rows: 10% 75% 10%;
        grid-template-areas:
          "header header"
          "nav main"
          "footer footer";
          }
  • 结合 grid-area 使用
css 复制代码
    .container {
        width: 100vw;
        height: 100vh;
        display: grid;
        grid-template-columns: 15% 80%;
        grid-template-rows: 10% 75% 10%;
        grid-template-areas:
          "header header"
          "nav main"
          "footer footer";
        .header {
          grid-area: header;
          background-color: rgb(245, 245, 245);
        }
        .nav {
          grid-area: nav;
          background-color: rgb(254, 243, 199);
        }
        .main {
          grid-area: main;
          background-color: rgb(217, 249, 157);
        }
        .footer {
          grid-area: footer;
          background-color: rgb(125, 211, 252);
        }
      }
html 复制代码
 <div class="container">
      <div class="header">header</div>

      <div class="nav">nav</div>

      <div class="main">main</div>

      <div class="footer">footer</div>

    </div>

这样就可以得到一个三行两列布局:

  • 第一行:header占满整行
  • 第二行:左侧nav,右侧main
  • 第三行:footer占满整行

💡 注意点

  1. 每一行的单词数量必须和grid-template-columns 定义的列数一致。

  2. "." 表示一个空白区域。

css 复制代码
grid-template-areas: "header header" "nav main" "footer .";

3. 一个区域必须是 矩形。 下述代码为错误示例:

css 复制代码
grid-template-areas: "header header" "header main" "footer ."

grid-template-areas 就是给网格区域起名字,然后通过 grid-area 把元素放进去,就像画表格一样排版。

1.4 grid-template

grid-template是以下三个属性的简写:

  • grid-template-rows
  • grid-template-columns
  • grid-template-areas

语法

css 复制代码
grid-template: <grid-template-rows> / <grid-template-columns>;
grid-template: <grid-template-areas>;
grid-template: <grid-template-areas> <grid-template-rows> / <grid-template-columns>;

示例:

css 复制代码
 grid-template: 10% 75% 10% / 15% 80%;
 /* 等价于 */
 grid-template-columns: 15% 80%;
 grid-template-rows: 10% 75% 10%;
css 复制代码
  grid-template:
          "header header"
          "nav main"
          "footer .";
        /* 等价于 */
 grid-template-areas:
          "header header"
          "nav main"
          "footer .";
css 复制代码
  grid-template:
          "header header" 10%
          "nav main" 75%
          "footer ." 10%
          / 15% 80%;
  /* 等价于 */
  grid-template-areas:
          "header header"
          "nav main"
          "footer .";
 grid-template-columns: 15% 80%;
 grid-template-rows: 10% 75% 10%;

1.5 grid

是一个更大范围的简写属性,同时可以设置以下属性:

  • grid-template-rows
  • grid-template-columns
  • grid-template-areas
  • grid-auto-rows
  • grid-auto-columns
  • grid-auto-flow

语法

css 复制代码
/* grid-template 简写 */
grid: <grid-template>;

/* 自动生成轨道简写 */
grid: <grid-auto-flow> <grid-auto-rows> / <grid-auto-columns>;

示例

css 复制代码
/*定义模板,等价于 grid-template 的写法*/
.container {
  display: grid;
  grid:
    "header header" 60px
    "sidebar main"  1fr
    "footer footer" 40px
    / 100px 1fr;
}
css 复制代码
/*定义自动布局*/
.container {
  display: grid;
  grid: auto-flow 100px / 1fr 1fr;
}
/*等价于*/
grid-auto-flow: row;
grid-auto-rows: 100px;
grid-template-columns: 1fr 1fr;

2. 间距控制

css 复制代码
  grid-column-gap: 10px;
  grid-row-gap: 5px;
  /*或者  上边为早期命名版本*/
  column-gap: 10px;
  row-gap: 5px;
  /*或同时设置 行 列*/
  gap: 5px 10px;

规范的早期版本将此属性命名为 grid-row-gap,为了保持与旧网站的兼容性,浏览器仍然会将 grid-row-gap 视为 row-gap 的别名。(MDN)

3. 对齐方式

对齐单元格内部的内容(items)

控制 grid item 在自己单元格中的对齐方式

  1. justify-items

设置单元格内项目在 水平方向 的对齐方式。

  1. align-items

设置单元格内项目在 垂直方向 的对齐方式。

  1. place-items justify-items + align-items 的简写。

对齐整个网格整体(content)

  1. justify-content

水平方向 上对齐整个网格。

  1. align-content

垂直方向 上对齐整个网格。

  1. place-contentjustify-content + align-content 的简写。

4. 自动生成规则

grid-auto-rows/ grid-auto-columns

定义隐式网络轨道的大小

显示网格:使用grid-template-rows / grid-template-columns 定义好的轨道。

隐式网格: 项目放置超出了定义的行/列时,浏览器"临时生成"的额外行/列。

css 复制代码
.container {
  display: grid;
  grid-template-columns: 100px 100px; /* 显式定义 2 列 */
  grid-auto-rows: 80px; /* 隐式行高度 */
}
html 复制代码
<div class="container">
  <div>A</div>
  <div>B</div>
  <!-- C 会被放在第 2 行,生成隐式行 -->
  <div>C</div>
</div>

grid-auto-flow

定义没有指定位置的项目如何被摆放。

  1. row(默认):先填充行,再换行。

显示网格是2列3行,刚好能放下6个元素。grid-auto-flow 来决定第7个元素的位置。

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .container {
        width: 50%;
        display: grid;
        grid-template-columns: 50% 50%;
        grid-template-rows: repeat(3, 200px);
        grid-auto-flow: row;
      }
    </style>
  </head>
  <body>
    <div class="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 class="item">7</div>
    </div>
    <script>
      const items = document.querySelectorAll(".item");
      items.forEach((item, index) => {
        item.style.backgroundColor = `rgb(${index * 200},${index * 50},${
          index * 20
        })`;
        item.style.color = "green";
      });
    </script>
  </body>
</html>
  1. column:先填充列,再换列。

grid-auto-flow: column;

  1. row dense / column dense:表示紧凑模式,尽量把空隙填满。

例如:一个元素占了2列,grid-auto-flow:row,则会有空隙。

html 复制代码
 <style>
      .container {
        width: 50%;
        display: grid;
        grid-template-columns: 50% 50%;
        grid-template-rows: repeat(3, 200px);
        grid-auto-flow: row;
      }
  </style>
<div class="container">
      <div class="item">1</div>
      <div class="item" style="grid-column: span 2">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
      <div class="item">6</div>
      <div class="item">7</div>
    </div>

grid-auto-flow:row dense,则不会有空隙。 后面元素会"往前挤",避免空隙 ,dense模式牺牲了"顺序",但更节省空间。 浏览器会尝试"回头补洞"

Grid Item(项目)

grid-column-start等

主要用来指定网格项在网格中的位置和跨度。

语法:

html 复制代码
grid-column-start: <line>;
grid-column-end: <line>;
grid-row-start: <line>;
grid-row-end: <line>;

<line> 表示网格线编号,或者用 span 表示跨多少行/列。

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .container {
        display: grid;
        grid-template-columns: repeat(3, 33%);
        grid-template-rows: repeat(2, 200px);
      }
      .item3 {
        grid-column-start: 1;
        grid-column-end: 3;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item3">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
      <div class="item">6</div>
      <div class="item">7</div>
    </div>
    <script>
      const items = document.querySelectorAll(".item");
      items.forEach((item, index) => {
        item.style.backgroundColor = `rgb(${index * 200},${index * 50},${
          index * 20
        })`;
        item.style.color = "green";
      });
    </script>
  </body>
</html>

表示item3这个元素区域是从第一条竖线到第三条竖线

grid-column / grid-row

是上述4个属性的简写。

css 复制代码
.item {
  grid-column: 1 / 3;  /* 相当于 start:1; end:3 */
  grid-row: 2 / 4;
}
css 复制代码
.item {
  grid-column: span 2; /* 跨两列 */
  grid-row: span 3;    /* 跨三行 */
}

grid-area

  1. 指定区域名字(配合grid-template-areas)
  2. 指定位置的缩写

语法:grid-area: <row-start> / <column-start> / <row-end> / <column-end>;

css 复制代码
.item {
  grid-area: 2 / 1 / 4 / 3;
}
/* 相当于 */
grid-row-start: 2;
grid-column-start: 1;
grid-row-end: 4;
grid-column-end: 3;

justify-self / align-self / place-self

用于 单个子项的对齐方式

  • justify-self:水平方向(x轴,行内方向)的对齐方式
  • align-self:垂直方向(y轴,列方向)的对齐方式
  • place-self:简写,语法是 place-self: align-self justify-self

进阶特性

fr单位

可分配空间的比例单位

css 复制代码
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: 2fr 1fr;

上述表示把列的剩余空间分为5份,第2列占2份,把行的剩余空间分为3份,第1行占两份。

repeat()

用于简化重复的网格轨道定义

css 复制代码
.container {
  display: grid;
  grid-template-columns: repeat(3, 200px);
}
/*相当于*/
grid-template-columns: 200px 200px 200px;

搭配fr实现等分:

css 复制代码
grid-template-columns: repeat(3, 1fr); /* 三等分 */

minmax()

定义一个轨道的最小值和最大值。常用场景:防止元素在小屏幕挤成 0 。

css 复制代码
/*表示列宽 至少 150px,但最多占据剩余空间的一份。*/
grid-template-columns: minmax(150px, 1fr);

auto-fill vs auto-fit

这两个和 repeat() + minmax() 一起用,常见于自适应布局:

css 复制代码
.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
}
  • auto-fill
    • 会尽可能多地生成轨道,哪怕没有内容。
    • 所以当容器变宽时,右边留着空白的列轨道
  • auto-fit
    • 会折叠掉没有内容的轨道。
    • 所以当容器变宽时,已有的元素会被拉伸填满整个宽度

命名网格线

css 复制代码
.container {
  display: grid;
  grid-template-columns: [sidebar-start] 200px [sidebar-end content-start] 1fr [content-end];
}

.sidebar {
  grid-column: sidebar-start / sidebar-end;
}
.content {
  grid-column: content-start / content-end;
}

层叠效果

css 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .container {
        padding: 50px;
        height: 60vh;
        font-size: 2rem;
        color: #fff;
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
      }
      .item1 {
        background-color: rgb(162, 192, 79);
        grid-area: 1 / 1 / 3 / 3;
        z-index: 1;
        border-radius: 15px;
      }
      .item2 {
        background-color: rgb(63, 63, 131);
        grid-area: 1 / 2 / 3 / 4;
        z-index: 2;
        border-radius: 15px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="item1">1</div>
      <div class="item2">2</div>
    </div>
  </body>
</html>

实战案例

两栏/三栏自适应布局

两栏布局

css 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .container {
        padding: 50px;
        height: 60vh;
        font-size: 2rem;
        color: #fff;
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        /*固定 + 自适应*/
        /* grid-template-columns: 200px 1fr;*/
      }
      .item1 {
        background-color: rgb(162, 192, 79);
        border-radius: 15px;
      }
      .item2 {
        background-color: rgb(63, 63, 131);
        border-radius: 15px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="item1">1</div>
      <div class="item2">2</div>
    </div>
  </body>
</html>

三栏布局

css 复制代码
grid-template-columns: repeat(3, 1fr);
 /*固定 + 自适应*/
/* grid-template-columns: 200px 1fr 1fr;*/

卡片式响应式布局

css 复制代码
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

圣杯布局

css 复制代码
grid-template-columns: 200px 1fr 350px;
相关推荐
ccnocare2 小时前
选择文件夹路径
前端
艾小码2 小时前
还在被超长列表卡到崩溃?3招搞定虚拟滚动,性能直接起飞!
前端·javascript·react.js
闰五月2 小时前
JavaScript作用域与作用域链详解
前端·面试
泉城老铁2 小时前
idea 优化卡顿
前端·后端·敏捷开发
前端康师傅2 小时前
JavaScript 作用域常见问题及解决方案
前端·javascript
司宸2 小时前
Prompt结构化输出:从入门到精通的系统指南
前端
我是日安2 小时前
从零到一打造 Vue3 响应式系统 Day 9 - Effect:调度器实现与应用
前端·vue.js
Mintopia2 小时前
🚀 Next.js 全栈 E2E 测试:Playwright vs Cypress
前端·javascript·next.js