Skip to content

grid 网格布局

在线学习网站

为什么需要 grid 布局?

一维 vs 二维

flexbox:一维布局

css
.container {
  display: flex;
  flex-direction: row; /* 或 column */
}

特点:沿单轴排列

  • 主轴方向:水平或者垂直。
  • 交叉轴:垂直于主轴。
  • 换行:自动到下一行/列。

grid:二维布局

css
.container {
  display: grid;
  grid-template-columns: 200px 100px 200px; /* 列轨道 */
  grid-template-rows: 100px 100px; /* 行轨道 */
}

特点:行列双向控制

  • 同时定义行和列。
  • 精确的网格单元格。
  • 元素可跨越多个格子。

⭐ grid 中的核心要素

  1. grid 容器:一旦声明,内部的 直接子元素 自动变成 grid 项
  2. 网格轨道:内容就在轨道里排列。
    • 行轨道:水平方向。
    • 列轨道:垂直方向。
  3. 网格线
    • 分割轨道的 坐标系
    • n 列的网格 = n + 1 条“垂直”线
    • n 行的网格 = n + 1 条“水平”线

定义网格蓝图

grid-template-columns

定义网格的 列轨道

css
.container {
  display: grid;
  /* 定义 3 列:第一列 200px,第二列 占据一份剩余空间,第三列 200px */
  grid-template-columns: 200px 1fr 200px;
}

grid-template-rows

定义网格的 行轨道

css
.container {
  display: grid;
  /* 定义 2 行:第一行高 100px,第二行高度由内容决定 */
  grid-template-rows: 100px auto;
}

gap

定义网格项之间的间距。

css
.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: 100px auto;
  /* 行间距和列间距均为 10px */
  gap: 10px;
  /* 或者分别定义行间距和列间距 */
  /* row-gap: 10px; */
  /* column-gap: 15px; */
}

轨道尺寸单位

固定单位:pxemrem

  • 提供可预测的、绝对的尺寸。
  • 适用于固定侧边栏宽度、导航栏高度等场景。

相对单位:%vwvh

  • 相对于容器或视口的尺寸。
  • 善于创建与父容器紧密关联的布局。

自动单位:auto

  • 由内容决定轨道尺寸。
  • 遵循“内容优先”原则。

弹性单位:fr

代表网格中,剩余“可用空间”的一份。

示例:等宽三列布局

css
.container {
  display: grid;
  /* 两条列间隙:2 * 20px = 40px */
  grid-template-columns:
    calc((100% - 40px) / 3)
    calc((100% - 40px) / 3)
    calc((100% - 40px) / 3);
  gap: 20px;
}
css
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px;
}

fr 的工作原理

css
.container {
  display: grid;
  width: 800px;
  grid-template-columns: 200px 1fr 2fr;
  gap: 20px;
}

计算过程:

  1. 总宽度:800px

  2. 固定宽度:200px(第一列)

  3. 间距总和:40px(2个 gap x 20px)

  4. 剩余空间:800px - 200px - 40px = 560px

    560px 是 1fr + 2fr 的总和

  5. fr 总份数:1fr + 2fr = 3fr

  6. 1fr 大小:560px / 3 = 186.67px

最终分配:

  • 第一列:200px(固定)
  • 第二列:186.67px(1fr)
  • 第三列:373.33px(2fr)

repeat() 函数

基础用法:

css
/* 传统写法 */
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
/* 使用 repeat() */
grid-template-columns: repeat(5, 1fr);

复杂模式重复:

css
/* 传统写法 */
grid-template-columns: 100px 1fr 100px 1fr 100px 1fr;
/* 使用 repeat() */
grid-template-columns: repeat(3, 100px 1fr);

与其他单位混合使用:

css
/* 传统写法 */
grid-template-columns: 50px 1fr 1fr 1fr 50px
/* 使用 repeat() */
grid-template-columns: 50px repeat(3, 1fr) 50px;

精准控制布局

基于网格线的精准定位

css
.item {
  /* 列方向定位 */
  grid-column-start: 1; /* 从第 1 条垂直线开始 */
  grid-column-end: 3; /* 到第 3 条垂直线结束 */
  /* 行方向定位 */
  grid-row-start: 2; /* 从第 2 条水平线开始 */
  grid-row-end: 4; /* 到第 4 条水平线结束 */
}
css
.item {
  /* 列方向定位 */
  grid-column: 1 / 3; /* 从第 1 条垂直线开始,到第 3 条垂直线结束 */
  /* 行方向定位 */
  grid-row: 2 / 4; /* 从第 2 条水平线开始,到第 4 条水平线结束 */
}

负数索引技巧:

-1 代表最后一条线,-2 代表倒数第二条线,以此类推。

css
.item-full-width {
  /* 从第一列延伸到最后一列 */
  grid-column: 1 / -1;
}

示例:3x3 网格布局

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 100px);
  grid-template-rows: repeat(3, 100px);
}

.item-1 {
  background-color: red;
  grid-column: 1 / 3;
  grid-row: 1 / 2;
}

.item-2 {
  background-color: green;
  grid-column: 1 / 3;
  grid-row: 2 / 3;
}

.item-3 {
  background-color: blue;
  grid-column: 3 / -1;
  grid-row: 1 / -1;
}

span 关键字实现动态跨越

基本语法:

css
.item-a {
  /* 从第 2 列开始,横跨 2 列 */
  grid-column: 2 / span 2;
}

.item-b {
  /* 自动放置,横跨 3 列 */
  grid-column: span 3;
}

span 的灵活性:

css
.responsive-item {
  /* 在小屏幕上横跨 2 列 */
  grid-column: span 2;
}

@media (min-width: 768px) {
  .responsive-item {
    /* 在大屏幕上横跨 4 列 */
    grid-column: span 4;
  }
}

命名网格区域

  • grid-area:将元素分配到命名区域。
  • grid-template-areas:定义网格区域布局。
css
.header {
  grid-area: header;
}
.nav {
  grid-area: nav;
}
.content {
  grid-area: content;
}
.aside {
  grid-area: aside;
}
.footer {
  grid-area: footer;
}

.responsive-layout {
  display: grid;
  grid-template-areas:
    'header'
    'nav'
    'content'
    'aside'
    'footer';
  grid-template-columns: 1fr;
  gap: 10px;
}

@media (min-width: 768px) {
  .responsive-layout {
    grid-template-areas:
      'header header'
      'nav content'
      'aside aside'
      'footer footer';
    grid-template-columns: 200px 1fr;
    gap: 10px;
  }
}

对齐

容器级对齐:控制网格在容器中的位置

当网格的总尺寸小于其容器尺寸时,控制整个网格在容器的位置

容器对齐属性:

  • justify-content:控制网格在 行轴(水平方向) 上对齐。
  • align-content:控制网格在 列轴(垂直方向) 上对齐。

常见对齐值:

  • start:网格在容器的起始位置对齐。
  • end:网格在容器的结束位置对齐。
  • center:网格在容器中居中。
  • space-around:轨道均匀分布,首尾距边缘为轨道间距的一半。
  • space-between:轨道均匀分布,首位轨道紧贴容器边缘。
  • space-evenly:完全均匀分布。
css
.container {
  width: 600px;
  height: 600px;

  display: grid;
  justify-content: center; /* 水平居中对齐 */
  align-content: center; /* 垂直居中对齐 */
  grid-template-columns: repeat(3, 100px);
  grid-template-rows: repeat(3, 100px);
  gap: 10px;
}

项目级对齐:控制项目在单元格内的位置

控制 单个网格项目在其分配到的单元格内部 的位置

容器统一定义:

  • justify-items:控制 所有项目 在各自单元格内的 水平对齐
  • align-items: 控制 所有项目 在各自单元格内的 垂直对齐

项目独立定义:

  • justify-self:控制 单个项目 在其单元格内的 水平对齐。会覆盖 justify-items
  • align-self:控制 单个项目 在其单元格内的 垂直对齐。会覆盖 align-items

可选值:

  • start:项目在单元格的起始位置对齐。
  • end:项目在单元格的结束位置对齐。
  • center:项目在单元格中居中。
  • stretch(默认值)项目拉伸以填满单元格。
css
.container {
  display: grid;
  grid-template-columns: repeat(3, 100px);
  grid-template-rows: repeat(3, 100px);
  gap: 10px;

  justify-items: center; /* 所有项目水平居中 */
  align-items: center; /* 所有项目垂直居中 */
}

.item-special {
  justify-self: start; /* 该项目水平靠左 */
  align-self: end; /* 该项目垂直靠下 */
}

grid 响应式技巧

minmax() 函数

minmax() 可以为轨道尺寸设定弹性边界。

css
minmax(min, max)
  • min:轨道的最小尺寸,保证内容的可读性。
  • max:轨道的最大尺寸,通常配合 1fr 等弹性单位。

基本示例:

css
.container {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) 500px minmax(200px, 1fr);
}

auto-fill 和 auto-fit 关键字

自动化布局的两种模式,这两个关键字都会在“可用空间”中尽可能地多创建指定尺寸的轨道,但在处理“剩余空间”的方式不同:

  1. auto-fill 保守填充

    • 用尽可能多的轨道填充容器。
    • 保留空轨道作为空白区域。
    • 适合希望保持轨道尺寸严格的场景。
  2. auto-fit 适应填满

    • 创建轨道后,折叠空轨道。
    • 让现有网格项拉伸填满容器。
    • 适合构建自适应卡片网格。
css
/* auto-fill */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

/* auto-fit */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

黄金组合

repeat() + minmax() + auto-*

自适应布局:

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

基于 MIT 许可发布