前端必备CSS布局之Grid布局

858 阅读10分钟

前言

《前端必备CSS布局之弹性(Flex)布局》这篇文章中,我们介绍了当今CSS的半壁江山——弹性布局,现在我们就来在这篇文章中讲完剩下的半壁江山——Grid布局。GO,GO,GO,出发咯。

一、什么是Grid布局?

定义

Grid 布局(网格布局)是 CSS 中最强大的布局系统之一,它将页面划分为二维网格(行和列),能轻松实现复杂的布局结构。相比 Flexbox 的一维布局,Grid 更适合整体页面布局或具有复杂嵌套关系的组件布局。

  • 核心概念
    • 网格容器(Grid Container) :应用display: grid(块级Grid容器)或display: inline-grid(行内级Grid容器)的元素,其所有直接子元素自动成为 “项目”。
    • 网格项目(Grid Items) :容器的直接子元素(不包含孙子元素,和弹性布局一样)。
    • 网格线(Grid Lines) :划分网格的线条(水平为行线,垂直为列线),编号从 1 开始。
    • 网格轨道(Grid Tracks) :行线或列线之间的区域(即 “行” 或 “列”)。
    • 网格单元格(Grid Cell) :单个行与列交叉的最小区域(类似表格的单元格)。
    • 网格区域(Grid Area) :多个相邻单元格组成的矩形区域。

示图

Grid布局示图.jpg

二、Grid布局属性

和 Flex 布局类似,Grid 布局的属性也分为容器属性和项目属性,分别控制容器和项目的规则。接下来我将分别讲述这两者。

(一)开启Grid布局

.container {
    display: grid;
}

(二)便捷操作

除了固定死的绝对单位px,Grid布局中还有一些属性可以便捷地进行布局设置。

相对尺寸单位(fr

除了可以设置绝对尺寸单位px,我们还可以使用fr这个相对单位。

  • fr:表示 “剩余空间的比例”。例如 1fr 2fr 表示两列按 1:2 分配剩余空间(先扣除固定尺寸,再分剩余,我感觉很像是弹性布局里面的flex-grow)。

  • 用法示例:这会创建三列,中间列的宽度是两侧列的两倍。

    .container {
      display: grid;
      grid-template-columns: 1fr 2fr 1fr;
      height: 200px;
    }
    
  • 完整示例

简化重复值(repeat()函数)

对于重复的值,可以使用repeat()函数来简化代码。例如 grid-template-columns: repeat(3, 1fr) 等价于 1fr 1fr 1frrepeat(2, 100px 200px) 等价于 100px 200px 100px 200px

  • 用法示例

    .container {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      /* 等同于 grid-template-columns: 1fr 1fr 1fr; */
    
      /* 也可以重复多个值 */
      grid-template-columns: repeat(2, 100px 200px);
      /* 等同于 grid-template-columns: 100px 200px 100px 200px; */
    }
    
  • 完整示例

尺寸范围(minmax()函数)

minmax()函数定义了一个大小范围,不小于最小值,不大于最大值。

  • 用法示例:下面的代码确保了第一列和第三列至少有100px宽,但可以根据可用空间扩展;第一行至少有50px高,但可以根据内容自动增高。

    .container {
      display: grid;
      grid-template-columns: minmax(100px, 1fr) 2fr minmax(100px, 1fr);
      grid-template-rows: minmax(50px, auto) 100px;
    }
    
  • 完整示例

自动填充列(auto-fill/auto-fit

auto-fill/auto-fit是 Grid 布局中用于实现响应式列布局的关键字,配合 repeat() 和 minmax() 使用,能根据容器宽度自动计算列数(无需媒体查询)。核心区别在于处理剩余空间时:auto-fill 保留空列,auto-fit 折叠空列并拉伸现有列。

  • 用法示例

    .container {
      display: grid;
      /* 尽可能创建更多的列,每列至少200px宽 */
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    
      /* 类似auto-fill,但会折叠空列 */
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    }
    
  • 完整示例

(三)容器属性(定义网格结构)

容器属性决定网格的行列结构、间距、对齐方式等,是布局的核心配置。

1. 定义网格结构

行列(grid-template-rows/grid-template-columns

这两个属性是Grid布局的核心,用于定义行轨道和列轨道的尺寸(其实就是每行每列各自的宽度)。

  • 语法grid-template-columns: <轨道尺寸>...(列);grid-template-rows: <轨道尺寸>...(行)。
  • 用法示例
    .container {
      display: grid;
      /* 分别定义了三列,其列尺寸为100px、200px、100px */
      grid-template-columns: 100px 200px 100px;
      /* 分别定义了两行,其行尺寸为50px、100px */
      grid-template-rows: 50px 100px;
    }
    
  • 完整示例:创建了一个3列2行的网格,其中列宽分别为100px、200px和100px,行高分别为50px和100px。
网格区域命名:grid-template-areas

通过命名区域简化项目定位(适合复杂布局,如页面布局),需配合项目的 grid-area 属性使用。

  • 规则

    • 用字符串表示行,同一行的区域用空格分隔
    • 同名区域必须形成矩形(不能是 “L” 形)
    • . 表示空单元格
  • 用法示例

    .container {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      grid-template-rows: auto auto auto;
      grid-template-areas: 
        "header header header"
        "sidebar content content"
        "footer footer footer";
    }
    
  • 完整示例

简写(grid-template

grid-templategrid-template-rowsgrid-template-columnsgrid-template-areas的简写属性。

  • 用法示例

    .container {
      display: grid;
      grid-template:
        "header header header" auto
        "sidebar content content" 1fr
        "footer footer footer" auto
        / 1fr 2fr 1fr;
    }
    
  • 完整示例

2. 网格间距(gap

gap, row-gap, column-gap这些属性用于设置网格线的大小(即行与行、列与列之间的间距)。

  • 用法示例

    .container {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
    
      /* 设置所有间距 */
      gap: 20px;
    
      /* 或者分别设置 */
      row-gap: 20px;
      column-gap: 10px;
    }
    
  • 完整示例

3. 对齐

网格对齐(整体网格在容器中的位置)

当网格总尺寸 <容器尺寸时,控制网格整体的对齐方式(区分 “项目在单元格内” 和 “网格在容器内”)。

  • 属性

    • 水平方向(行轴)justify-content
    • 垂直方向(列轴)align-content
  • 简写place-content: 垂直 水平(单值时两者相同)

    .container {
      display: grid;
      /* 同时设置垂直和水平对齐 */
      place-content: center; /* 等同于 align-content: center; justify-content: center; */
      place-content: start end; /* 等同于 align-content: start; justify-content: end; */
    }
    
  • 取值说明(共通)

    • start:靠起始端对齐(左 / 上)
    • end:靠结束端对齐(右 / 下)
    • center:居中
    • space-between:两端对齐,中间间距平均
    • space-around:项目两侧间距相等(边缘间距是中间的一半)
    • space-evenly:所有间距(包括边缘)完全相等
  • 完整示例

项目对齐(项目在单元格内的位置)

控制所有项目在各自单元格内的对齐方式(单元格是项目的 “容器”)。

  • 属性

    • 水平方向justify-items
    • 垂直方向align-items
  • 简写place-items: 垂直 水平

    .container {
      display: grid;
      /* 同时设置垂直和水平项目对齐 */
      place-items: center; /* 等同于 align-items: center; justify-items: center; */
      place-items: start end; /* 等同于 align-items: start; justify-items: end; */
    }
    
  • 取值说明(共通)

    • start:单元格起始端(左 / 上)
    • end:单元格结束端(右 / 下)
    • center:单元格居中
    • stretch:默认值,拉伸填满单元格
  • 完整示例

4. 隐式轨道(grid-auto-rows / grid-auto-columns

当项目数量超过定义的行列数时,Grid 会自动创建 “隐式轨道”(默认尺寸为 auto)。grid-auto-rows 以及 grid-auto-columns这两个属性用于定义隐式轨道的尺寸。

  • 注意:隐式不代表看不到,作为一个完整的布局系统,Grid 不会让多余的项目 “消失” 或 “溢出容器”,而是会自动创建新的轨道来放置剩余项目。这些 “额外创建的轨道” 就是隐式轨道

  • 用法示例:定义 2 行,但有 5 个项目(会生成 3 行隐式轨道):

    .container {
      grid-template-rows: 50px 50px; /* 显式定义 2 行 */
      grid-auto-rows: 80px; /* 隐式行轨道高度为 80px */
    }
    
  • 完整示例

(四)项目属性(控制项目位置和大小)

项目属性用于调整单个项目的布局(覆盖容器的默认设置)。

1. 项目定位(grid-column / grid-row

通过「网格线编号」或「跨轨道数量」控制项目占据的行列范围(核心属性)。

  • 语法
    • grid-column: 起始列线 / 结束列线(简写,等价于 grid-column-start / grid-column-end
    • grid-row: 起始行线 / 结束行线(等价于 grid-row-start / grid-row-end
  • 关键用法
    • 网格线编号:从 1 开始(例如 grid-column: 1 / 3 表示从第 1 列线到第 3 列线,跨 2 列)。
    • span 关键字:表示 “跨多少轨道”(例如 grid-column: 1 / span 2 等价于 1 / 3)。
  • 示例代码

2. 关联区域(grid-area

配合容器的 grid-template-areas 使用,指定项目属于哪个命名区域。

  • 用法示例:将项目对应到 header 区域。

    .header { 
        grid-area: header; /* 对应容器中定义的 header 区域 */ 
    }
    

也可直接用网格线简写:grid-area: 起始行线 / 起始列线 / 结束行线 / 结束列线(等价于 grid-row + grid-column)。

  • 完整示例

3. 单个项目对齐(justify-self / align-self

覆盖容器的 justify-items / align-items,单独控制某个项目在单元格内的对齐方式。

  • 取值同 justify-items / align-itemsstart/end/center/stretch)。

  • 简写:place-self: 垂直 水平

  • 完整示例

三、Grid布局实战

1. 经典网页布局

2. 照片墙布局

3. 仪表盘布局

四、兼容性问题

  • 支持:Grid布局现在已经得到了所有主流浏览器的良好支持:

    • Chrome 57+
    • Firefox 52+
    • Safari 10.1+
    • Edge 16+
    • Opera 44+
  • 不支持:IE 全版本

支持旧版

对于需要支持旧版浏览器的项目,可以考虑使用以下策略:

1. 检测兼容性

  • CSS原生检测(推荐):使用@supports规则检测浏览器是否支持Grid

    /* 支持Grid的浏览器用Grid样式 */
    @supports (display: grid) {
      .container { display: grid; /* 其他Grid属性 */ }
    }
    
    /* 不支持的用后备样式 */
    @supports not (display: grid) {
      .container { display: flex; /* 其他降级样式 */ }
    }
    
  • JS 辅助检测(复杂场景用)

    const supportsGrid = window.CSS?.supports('display', 'grid'); 
    // 根据结果动态添加类名或样式
    

2. 降级策略

  • 主要方案:用 Flexbox 替代(支持更早,适配一维布局)

    • 多列布局:flex-wrap: wrap + 百分比宽度
    • 模拟 gap:父容器负 margin + 子元素 padding
  • 工具辅助:用 Autoprefixer 自动添加浏览器前缀(如 IE11 的-ms-前缀)

项目运用

  • 现代项目(无 IE 需求):直接用 Grid,无需过度降级
  • 需兼容旧浏览器:先实现 Flexbox 基础布局,再用 Grid 增强现代浏览器体验

结语

CSS Grid布局是一个强大而灵活的布局系统,它彻底改变了我们设计网页布局的方式。虽然学习曲线可能比Flexbox稍陡,但掌握Grid布局绝对值得投入时间,它将成为你前端开发工具箱中的强大武器。最佳实践是将Grid用于整体页面布局,而Flexbox用于组件内部的一维布局,两者结合使用可以创建出既灵活又强大的现代网页布局。
如果这篇文章有帮助到你,不胜荣幸;如果文章有错误或者缺漏,请在评论区指出,大家一起进步,谢谢🙏。