Flex布局常用在单行/单列排列的这种一维场景下,比如导航栏,而像商品列表、图片墙这种需要严格对齐行和列的二维场景更适合使用Grid布局。
戳这里回顾Flex布局👇
Flex布局全解析,看这一篇就够了
一、Grid布局基础概念
Grid 布局(网格布局)是 CSS 中一种二维布局模型,允许开发者通过行(Row)和列(Column)的组合,将页面划分为多个区域,并精准控制元素的位置和尺寸。它的核心特点是同时管理行和列,适合构建复杂且结构化的布局。
 
1. 容器(Container)与项目(Item)
- 容器:通过 display: grid或display: inline-grid定义(容器元素默认是块级元素,但也可以通过inline-grid设成行内元素)
- 项目:容器的直接子元素自动成为项目,容器包含一个或多个项目(仅第一层子元素参与布局)
<!DOCTYPE html>
<html>
<head>
  <style>
    .grid-container {
      display: grid;
      grid-template-columns: auto auto auto;
      width: 300px;
      height: 200px;
    }
    .grid-item {
      background-color: #409eff;
      width: 100px;
      height: 100px;
      border: 1px solid #000000;
    }
  </style>
</head>
<body>
  <div class="grid-container">
    <div class="grid-item">item 1</div>
    <div class="grid-item">item 2</div>
    <div class="grid-item">item 3</div>
    <div class="grid-item">item 4</div>
    <div class="grid-item">item 5</div>
    <div class="grid-item">item 6</div>
  </div>
</body>
</html>
不使用 display: grid 的效果:

使用 display: grid 的效果:
2. 网格线(Grid Line)
- 划分网格的横向(行)和纵向(列)的线,通过数字索引(从 1 开始)或自定义名称引用
- 示例:一个 3x3 网格有 4 条垂直线(列)和 4 条水平线(行)
3. 轨道(Track)
- 示例:grid-template-columns: 100px 200px定义两列,宽度分别为 100px 和 200px
4. 单元格(Cell)与区域(Area)
- 区域:一个或多个单元格组成的矩形区域,可通过命名或坐标定义
二、容器属性详解
以下8类属性设置在容器上:
1. grid-template-columns / grid-template-rows:定义每一行的(显式)列宽 / 行高
.container {
  /* 浏览器自己决定长度 */
  grid-template-columns: auto auto;
  /* 固定列宽,定义了两列 */
  grid-template-columns: 100px 200px;
  grid-template-columns: 25% 75%;
  /* 使用 fr 单位(剩余空间比例) */
  grid-template-columns: 1fr 2fr;
    /* 第一列占 100px,第二、三列按比例分剩余空间且第三列是第二列的两倍 */
  grid-template-columns: 100px 1fr 2fr;
  /* 定义列宽 100px,尽可能多地创建列 */
  grid-template-columns: repeat(auto-fill, 100px);
  /* 规定列宽范围,尽可能撑到最大 */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  /* 混合单位与函数 */
  grid-template-columns: repeat(3, 1fr) minmax(200px, auto);
}
- fr:(fraction)一个 fr 单位代表网格容器中剩余可用空间的一等份,表示比例关系
- repeat():接受两个参数,参数一是重复的次数,参数二是要重复的值
     示例:
- repeat(3, 1fr)等同于- 1fr 1fr 1fr,简化代码
- repeat(2, 50px 100px)等同于- 50px 100px 50px 100px
- auto-fill:单元格宽度固定,容器宽度不固定。尽可能多地创建列,即使没有内容,也会保留空轨道
- auto-fit:单元格宽度不固定,容器宽度固定。会将空轨道折叠,让现有列尽量填充空间
- minmax():接受两个参数,参数一为最小值,参数二为最大值,大小需在这个范围内
auto-fill和auto-fit的区别:
- 当容器足够宽时,auto-fill可能生成多个空列,而auto-fit会让已有的列扩展填满示例:若容器宽度为400px,minmax(50px, 1fr):
- auto-fill:生成 8 列(每列 50px),留空未使用空间
- auto-fit:生成 8 列后折叠空轨道,将总宽度均分给现有列(如 2 列时每列 400px)
 
2. column-gap / row-gap:设置列间距 / 行间距
.container {
  row-gap: 20px;
  column-gap: 20px;
  gap: 20px;        /* 行和列间距均为 20px */
  gap: 10px 30px;   /* 行间距 10px,列间距 30px */
}

3. grid-template-areas:定义区域
.container {
  display: grid;
  /* 分出9个单元格 */
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
  /* 将9个单元格分成多个区域 */
  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; }

4. grid-auto-flow:定义项目放置顺序
.container {
  grid-auto-flow: row | column | row dense | column dense;
}
- dense:启用“紧凑模式”,自动填补前面留下的空隙

5. justify-items / align-items / place-items:各个项目在单元格内的对齐方式
.container {
  /* 控制项目在单元格内的水平对齐方式 */
  justify-items: stretch | start | end | center; 
  /* 控制项目在单元格内的垂直对齐方式 */
  align-items: stretch | start | end | center; 
  /* 简写 */
  place-items: <align-items> <justify-items>;
}
- stretch:默认值,拉伸至占满单元格的整个宽度(项目大小未指定)

6. justify-content / align-content / place-content:整个内容区域在容器内的对齐方式
.container {
  /* 控制整个内容区域在容器内的水平对齐方式 */
  justify-content: stretch | start | end | center | space-around | space-between | space-evenly;
  /* 控制整个内容区域在容器内的垂直对齐方式 */
  align-content: stretch | start | end | center | space-around | space-between | space-evenly;  
  /* 简写 */
  place-items: <align-content> <justify-content>;
}
- stretch:默认值,拉伸至占满整个网格容器(需配合 grid-template-columns: auto 或未设置固定列宽)
- space-between:两端对齐,项目之间间距相等,首尾项目与容器边缘没有间距
- space-around:项目两侧的间距相等,首尾项目与容器边缘的间距是项目之间间距的一半
- space-evenly:项目之间间距相等,首尾项目与容器边缘的间距也等于项目之间间距

7. grid-auto-columns / grid-auto-rows:定义每一行的(隐式)列宽 / 行高
.container {
  /* 属性值写法和 grid-template-columns 的相同*/
  grid-auto-columns: <track-size>;
}
- 当网格项目数量超出显式定义的网格行数时,浏览器会自动创建新的行,而 grid-auto-columns/grid-auto-rows决定了这些隐式行的宽度/高度
触发场景:

8. grid-template  / grid:简写属性
.container {
  grid: 
    /* grid-template-rows 和 grid-template-columns 用 / 分隔 */
    [grid-template-rows] / [grid-template-columns] 
    /* 可选,需紧跟在尺寸定义后 */
    [grid-template-areas] 
    /* 可选,顺序自由 */
    [grid-auto-flow]
    [grid-auto-rows] [grid-auto-columns] ;
}
- grid-template是- grid-template-columns、- grid-template-rows和- grid-template-areas这三个属性的简写
- grid是- grid-template-rows、- grid-template-columns、- grid-template-areas、- grid-auto-rows、- grid-auto-columns、- grid-auto-flow这六个属性的简写
三、项目属性详解
以下4类属性设置在项目上:
1. grid-column-start / grid-column-end / grid-row-start / grid-row-end / grid-column / grid-row:定义项目占据的列/行范围
.item {
  /* 通过网格线编号定位 */
  grid-column-start: 2;  /* 项目左边框是第二根垂直网格线 */
  grid-column-end: 3 ;  /* 项目右边框是第三根垂直网格线 */
  grid-row-start: 2 ;  /* 项目上边框是第二根水平网格线 */
  grid-row-end: 4 ;  /* 项目下边框是第四根水平网格线 */
  /* 简写 */
  grid-column: <start-line> / <end-line>;
  grid-row: <start-line> / <end-line>;
  grid-column: 1 / span 2;  /* 等同于 grid-column: 1 / 3; */
  grid-row: 1 / span 2;
  /* 可以只写一个编号,默认跨越一个网格 */
  grid-column: 2;
}
- 除了指定为第几根网格线,还可以指定为网格线的名字,例如 grid-column-start: header-start

2. grid-area:将项目分配到命名区域,或通过行/列起止线自定义位置
.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
  grid-template-areas:
    "header header header"
    "sidebar main main"
    "footer footer footer";
}
.item {
  /* 等同于:grid-row: 1 / 2; grid-column: 1 / 4; */
  grid-area: header;  /* 分配到 header 区域 */
  /* 也可以简写为 grid-area: <row-start> / <column-start> / <row-end> / <column-end>; */
  grid-area: 1 / 1 / 2 / 4;
}
3. justify-self / align-self  / place-self:单个项目在单元格内的对齐方式
.container {
  /* 控制项目在单元格内的水平对齐方式 */
  justify-self: stretch | start | end | center; 
  /* 控制项目在单元格内的垂直对齐方式 */
  align-self: stretch | start | end | center; 
  /* 简写 */
  place-self: <align-self> <justify-self>;
}
- 与容器的 justify-items/align-items属性的用法完全一致,但只作用于单个项目
四、实战代码示例
示例1:响应式网格系统
<!DOCTYPE html>
<html>
  <head>
    <style>
      .grid-container {
        display: grid;
        gap: 20px;
        padding: 20px;
        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
      }
      .grid-item {
        background: #409eff;
        padding: 20px;
        color: white;
        border-radius: 8px;
      }
        
    </style>
  </head>
  <body>
    <div class="grid-container">
      <div class="grid-item">Item 1</div>
      <div class="grid-item">Item 2</div>
      <div class="grid-item">Item 3</div>
      <div class="grid-item">Item 4</div>
      <div class="grid-item">Item 5</div>
      <div class="grid-item">Item 6</div>
    </div>
  </body>
</html>  

示例2:圣杯布局(Holy Grail)
<!DOCTYPE html>
<html>
<head>
  <style>
    .layout {
      display: grid;
      height: 100vh;
      grid-template:
        "header header header"80px
        "nav    main   aside"1fr
        "footer footer footer"60px
        / 200px1fr 150px;
    }
    .header {
      grid-area: header;
      background: #333;
      color: white;
      padding: 1rem;
      display: flex;
      align-items: center;
    }
    .nav {
      grid-area: nav;
      background: #f0f0f0;
      padding: 1rem;
      border-right: 1px solid #ddd;
    }
    .main {
      grid-area: main;
      padding: 2rem;
      background: white;
    }
    .aside {
      grid-area: aside;
      background: #f8f8f8;
      padding: 1rem;
      border-left: 1px solid #ddd;
    }
    .footer {
      grid-area: footer;
      background: #333;
      color: white;
      padding: 1rem;
      display: flex;
      align-items: center;
    }
  </style>
</head>
<body>
  <div class="layout">
    <header class="header">网站标题</header>
    <nav class="nav">
      <h2>导航菜单</h2>
      <ul>
        <li>菜单项1</li>
        <li>菜单项2</li>
      </ul>
    </nav>
    <main class="main">
      <h1>主要内容区</h1>
      <p>这里是页面主要内容...</p>
    </main>
    <aside class="aside">
      <h3>侧边栏</h3>
      <p>相关链接...</p>
    </aside>
    <footer class="footer">xxx版权所有</footer>
  </div>
</body>
</html>

示例3:瀑布流布局
<!DOCTYPE html>
<html>
<head>
  <style>
    .masonry {
      display: grid;
      gap: 16px;
      padding: 20px;
      grid-template-columns: repeat(4, 1fr);
      grid-auto-rows: 80px;
    }
    .masonry-item {
      background: #2196F3;
      color: white;
      padding: 1rem;
      border-radius: 4px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    /* 随机高度模拟 */
    .masonry-item:nth-child(2n) {
      grid-row: span 2;
      background: #FF5722;
    }
    .masonry-item:nth-child(3n) {
      grid-row: span 3;
      background: #4CAF50;
    }
    .masonry-item:nth-child(5n) {
      grid-row: span 4;
      background: #9C27B0;
    }
  </style>
</head>
<body>
  <div class="masonry">
    <div class="masonry-item">内容块1</div>
    <div class="masonry-item">内容块2</div>
    <div class="masonry-item">内容块3</div>
    <div class="masonry-item">内容块4</div>
    <div class="masonry-item">内容块5</div>
    <div class="masonry-item">内容块6</div>
    <div class="masonry-item">内容块7</div>
    <div class="masonry-item">内容块8</div>
  </div>
</body>
</html>
 
阅读原文:原文链接
该文章在 2025/3/21 10:38:12 编辑过