前端笔记 - 【CSS】- Grid布局详解(附带详细案例)

前言

  • 目前为止,我经常在开发中使用的布局方式有以下几种:
    • Flex布局;
    • 定位;
    • 浮动(基本不怎么使用);
  • 最近在做一个项目的时候,使用到了网格布局,真的是方便了许多;
  • 下面就来一起瞅瞅最强布局方式吧!
  • 最近在项目中也是有使用到,有些时候是真的好用啊;

一、Grid布局介绍

1.1 Grid布局是什么?

  • 概念
    • Grid布局即网格布局,相信大家多多少少都是听说过的,它是一种新的CSS布局模型,主要作用是将一个页面或元素划分为几个区域,以及定义这些区域的大小、位置、层次等关系;
    • 它将一个页面或元素划分为一个个的网格,可以任意组合不同的网格,做出各种各样的布局;
    • Grid布局是目前唯一一种 CSS二维布局 方案,他将一个元素划分为

1.2 Grid布局的优缺点

  • 优点
    • 更灵活的排版方式
      • Grid 布局可以对网页进行更加灵活的布局设计,允许多列和多行的布局,且支持在不同列和行的交叉位置进行对齐;
    • 简化HTML结构
      • 相比传统的布局方式,Grid布局可以减少HTML结构中的 divclass 的使用;
    • 更容易实现响应式布局
      • Grid布局基于强大的网格系统设计,支持自适应布局与媒体查询;
    • 可以将多个项目放入网格单元格或区域中,它们可以彼此部分重叠。然后可以用z-index属性控制该分层;
  • 缺点
    • 属性较多,难记忆;
    • 兼容性略差;

1.3 Gird布局 和 Flex布局 的区别和使用场景

1.3.1 Flex布局

  • 一维布局 方式;
    • 布局一次只能处理一个维度上的元素布局【一行或一列】;
  • 适用于局部布局方式;

1.3.2 Griud布局

  • 二维布局 方式;
    • Grid布局是将容器划分为了 " " 和 "",产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到我们的目的,实现我们需要的效果;
  • 通常用于整个页面的规划
  • Grid布局 远比 Flex布局 要强大;

1.3.3总结

  • Grid布局 与 Flex布局有一定的相似性,都可以指定容器内部多个元素的位置;但是,它们也存在重大区别;
  • Grid布局 可以做 Flex布局做不了的事,Flex布局 比 Grid布局 兼容性要好,它们可以共同工作。Grid Item 可以做为 FlexBox 的容器,Flex Item 也可以作为 Grid容器;
  • 综上所述,可以根据业务场景需求选择相应的布局方式;

1.4 Grid布局关键词的基本概念

1.4.1 基本演示

  • 🎯 在线代码演示 🎯

    html 复制代码
    <!-- 网格容器 -->
    <div class="grid-container">
      <!-- 网格元素 -->
      <div class="grid-item one">One</div>
      <div class="grid-item two">Two</div>
      <div class="grid-item three">Three</div>
      <div class="grid-item four">Four</div>
      <div class="grid-item five">Five</div>
      <div class="grid-item six">Six</div>
    </div>
    css 复制代码
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      padding: 50px;
    }
    
    .grid-container {
      display: grid; /* 声明一个Grid容器 */
      grid-template-columns: repeat(3, 200px); /* 声明列数和每列的宽度,3列,每一列宽度为 200px */
      /* grid-gap: 20px 20px; 该行代码等同于下面这行代码 */
      gap: 20px; /* 声明行间距和列间距 */
      grid-template-rows: 100px 200px; /* 声明行的高度 - 第一行100px,第二行200px,两行之外的行会将剩余高度均分 */
      width: fit-content; /* 元素的宽度为由内容的宽度撑开 */
      border: 2px solid red;
      border-radius: 4px;
      background-color: #eee;
    }
    
    .one {
      background: #18dfbe;
    }
    
    .two {
      background: #ff49f8;
    }
    
    .three {
      background: #0bc530;
    }
    
    .four {
      background: #38d1d8;
    }
    
    .five {
      background: #edbf7e;
    }
    
    .six {
      background: #551ccE;
    }
    
    .grid-item {
      text-align: center;
      font-size: 200%;
      color: #fff;
    }

1.4.2 网格容器 和 网格项目

  • 通过在 元素上声明 display: grid / inline-grid; 来创建一个 网格容器
  • 一旦这样做了,这个元素的所有 直系子元素(亲子元素) 将成为 网格项目;
  • 按照上面的列子来说,.grid-container所在的元素为一个网格容器,其直系子元素将成为网格项目;

1.4.3 网格轨道

  • 网格轨道分为两部分:行 和 列;
  • grid-template-columns 属性来定义网格中的 ,容器内部 垂直区域 称之为
  • grid-template-rows 属性定义网格中的 ,容器内部 水平区域 称之为
  • 这些属性定义了网格的轨道,一个网格轨道就是网格中任意两条线之间的空间;

1.4.4 网格单元(网格项目)

  • 一个网格单元是在一个网格元素中最小的单位,上图中的六个元素都是一个个的网格单元;

1.4.5 网格线

  • 划分网格的线称之为"网格线"。
  • 需要注意的是,当我们定义网格时,我们定义的是网格轨道,而不是网格线;
  • Grid会为我们创建编号的网格线来让我们定位每一个网格元素。m列有m+1根垂直网格线,n行有n+1根水平网格线。按照本例来说,有4根垂直网格线,3根水平网格线;
  • 网格线的编号顺序:
    • 一般来说,是从左到右,从上到下,1, 2, 3, ......依次 递增 进行编号(左边上边);
    • 当然也可以从右到左,从下到上进行编号,按照-1, -2, -3, ......依次 递减 的顺序编号(右边下边);
  • 浏览器中如何查看网格线?
    • F12 打开控制面板,我们找到网格容器,点击 grid 即可看到;

二、网格容器属性介绍

  • 开始介绍属性之前,需要对上述案例代码进行一点改造;需要给grid-container设置宽高为800px 600px,并且对每个 grid-item 添加边框border: 2px dashed #333;,方便我们查看效果;
  • Grid布局相关的属性以及属性值比较多,为了方便记忆,可以自己动手敲一敲(我也会在某个属性的介绍中做个小案例,方便理解);

2.1 display

  • 我们通过在元素上添加 display: grid / inline-grid; 来创建一个网格容器。
  • 🎯 在线代码演示 🎯
    • 两种属性值的区别:
      • grid
        • 块级元素;
      • inline-grid
        • 行内元素;

2.2 设置 列宽 和 行高(grid-template-columns + grid-template-rows)

  • grid-template-columns 属性 设置 列宽
  • grid-template-rows 属性 设置 行高

2.2.1 固定的列宽和行高

  • 🎯 在线代码演示 🎯

    css 复制代码
    /* 固定 的 列宽 和 行高 */
    .grid-container {
      /* 声明了三列,第一列的宽度:300px;第二列的宽度:200px;第三列的宽度:300px */
      grid-template-columns: 200px 200px 300px;
      /* 声明了两行,第一行的高度:200px;第二行的高度是:150px */
      grid-template-rows: 150px 150px;
    }

2.2.2 简化重复的值 - repeat()

  • 可以简化重复的值;

  • 该函数接收两个值:

    • 第一个值:重复的次数
    • 第二个值:重复的值
  • 🎯 在线代码演示 🎯

  • 上面的代码等同于下面这段代码:

    css 复制代码
    .grid-container {
      /* 声明了三列,第一列的宽度:300px;第二列的宽度:200px;第三列的宽度:300px */
      grid-template-columns: repeat(2, 200px) 300px;
      /* 声明了两行,高度一样,使用 repeat() 进行简化 */
      grid-template-rows: repeat(2, 150px);
    }

2.2.3 自动填充 - (auto-fill)

  • auto-fill的前身是auto-fitauto-fit属性已弃用(也能生效);

  • 表示自动填充,让一行或一列中尽可能容纳更多的单元格;

    • 当前这一行的列数不固定(看当前浏览器可视窗口的宽度能放多少个列宽的项目) 或者 这一列的行数不固定;
  • 注意

    • 测试的时候,不要将网格容器的宽度写死,这样改变浏览器可视化窗口的时候的能看到效果;
  • 🎯 在线代码演示 🎯

    css 复制代码
    grid-template-columns: repeat(auto-fill, 150px);
    /* 这行代码表示,当前这一行的列数不固定(看当前浏览器可视窗口能放多少个150px宽的项目),每列的宽度为150px */

2.2.4 fr关键字

  • Grid布局还引入了一个另外的长度单位来帮助我们创建灵活的网格轨道。fr单位代表网格容器中可用空间的几等份;
  • fr关键 和 flex关键字极为相似,都是将剩余部进行均分;
    • 如何均分?
      • 拿到剩余部分,看当前网格容器写了几个fr,就表示均为多少分,根据fr的数值进行划分;
  • 🎯 在线代码演示 🎯
    • 浏览器可视化窗口宽度最小的时候,2、3;4、5不改变大小是因为里面有内容;

2.2.5 minmax() 函数

  • 我们有时候想给网格元素一个最大宽度和最小宽度,minmax()函数产生一个长度范围,表示长度在这个范围之中都可以应用到网格项目中;
  • 它接收两个参数:
    • 第一个参数:最小值;
    • 第二个参数:最大值;
  • 🎯 在线代码演示 🎯

2.2.6 宽度或高度自适应 - auto关键字

  • 通过 auto关键字,我们可以轻松实现两列甚至更多列的布局(其中的一列或某几列宽度固定不变,其他的列宽度随着屏幕的宽度自适应);
    • 通常在做一些电商网站或者政府网站的时候,可以使用auto(这种情况可以使用,但是不推荐,政府的网站有时候可能会在低版本浏览器上运行,Grid布局对浏览器的版本要求又比较高,我电脑上的69版的谷歌运行起来是没有问题);
  • 🎯 在线代码演示 🎯

2.3 设置 行间距 和 列间距(gap + row-gap + column-gap)

最新属性 作用 前身 说明
gap 设置 行间距 和 列间距(先行后列 grid-gap 该属性是下面两个属性的复合属性
row-gap 设置 行间距 grid-row-gap
column-gap 设置 列间距 grid-column-gap
  • ❗❗ 注意
    • 写复合属性的时候,column-gap属性是可选的,假如该属性缺失的话,则会被设置成与 row-gap 一样的值
  • 🎯 在线代码演示 🎯

    css 复制代码
    /* row-gap: 30px; */
    /* column-gap: 60px; */
    /* 上面的代码等同于下面这行代码 */
    gap: 30px 100px; /* 行间距, 列间距 */

2.4 ❌ 定义区域(grid-template-areas)

  • 不推荐使用该属性,要使用该属性就必须和项目属性grid-area结合使用;
    • 结合使用的话,必须要使用grid-area属性给每个项目进行命名,如果项目比较少还可以,项目很多的话,真的是很头疼;
    • 而且要使用该属性定义网格区域的话,必须要保证网格区块是个矩形,真的是很烦人;
  • grid-area属性可以单独使用,并且单独使用的性价比要比这两种属性结合使用的性价比高得多,我们也方便; grid-rear属性的详细使用请看 三、网格项目属性介绍 - 3.2
  • grid-template-areas属性用来 定义区域一个区域一个 或者 多个单元格 组成;
  • 一般这个属性跟 网格元素grid-area 属性一起使用:
    • grid-area属性指定项目放在哪一个区域;
  • 注意
    • 每一个给定的字符串会生成一行,一个字符串中用空格分隔的每一个单元格会生成一列;
    • 多个同名的,跨越相邻行或列的单元格 称为 网格区块
    • 非矩形网格区块无效的
    • .(空单元格)只能出现在该行的首和尾,不能出现在中间;
      • 因为,放在中间组成的网格区块是无效的;
  • 🎯 在线代码演示 🎯
css 复制代码
.grid-container {
  /* 声明三行三列 */
  /* . 表示当前单元格为空 */
  grid-template-areas: ". head head" "left right right" "left right right";

  /* 声明3列 */
  /* 第一列:列宽为 100px */
  /* 第二列 和 第三列 列宽相等为: 200px */
  grid-template-columns: 100px repeat(2, 200px);
  
  /* 声明三行,每行的行高为100px */
  grid-template-rows: repeat(3, 100px);
  
  /* 行间距和列间距为 4px */
  grid-gap: 4px;
  
  /* 容器宽度由内容撑开 */
  width: fit-content;
}
css 复制代码
/* 将class为 .one 的元素放在 head区域 */
.one {
  grid-area: head;
}

/* 将class为 .two 的元素放在 left区域 */
.two {
  grid-area: left;
}

/* 将class为 .three 的元素放在 right区域 */
.three {
  grid-area: right;
}

2.5 元素排列方式(grid-auto-flow)

  • 该属性控制着自动布局算法怎样运作,精确指定在网格中被自动布局的元素怎样排列;
  • 默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,如果某个项目(单元格)的宽度太大,在当前行已经放不下了,就会放弃当前行,自动填入到下一行;
属性名 属性值 描述
grid-auto-flow row 默认值,按 开始排列,即先填满一行,再开始下一行
column 开始排列
dense 该关键字指定自动布局算法使用一种"稠密"堆积算法,如果后面出现了稍小的元素,则会试图去填充网格中前面留下的空白。这样做会填上稍大元素留下的空白,但同时也可能导致原来出现的次序被打乱
row dense 按行来填充网格中前面留下的空白(请参考下面的例子来看)
column dense 按列来填充网格中前面留下的空白(请参考下面的例子来看)
  • 🎯 在线代码演示 🎯

    css 复制代码
    /* 网格容器 */
    .grid-container {
      grid-auto-flow: row; /* 网格项目的排列方式 - 默认值 - row */
    }

2.6 设置网格在容器中的位置(justify-content + align-content)

  • justify-content
    • 该属性用于对齐容器内的网格,设置如何分配顺着弹性容器主轴(或者网格行轴)的元素之间及其周围的空间;
    • 简单来说就是根据 网格行轴 设置 网格位置 以及 列间距
  • align-center
    • 该属性用于设置 垂直方向 上的 网格元素 在容器中的 对齐方式
    • 简单来说就是根据 网格列轴 设置 网格位置 及其 行间距
  • ❗❗ 注意
    • 网格的总宽度 必须小于 容器的宽度 才能使 justify-content 属性生效;
    • 网格元素的总高度 必须小于 容器的高度 才能使 align-content 属性生效;
    • justify-contentalign-content 的属性值是一样的;
属性值 描述(说明) 效果展示
start 放在开始位置
end 放在结束位置
space-between 第一列(第一行)放在开始位置,最后一列(最后一行)放在结束位置,列(行)间距相等
space-around 列(行)两侧的间距相等
space-evenly 列(行)间距与两侧空白相等

2.7 设置网格内容在网格中的位置(justify-items + align-items)

  • 注意
    • 该属性会改变网格元素的大小;
属性值 描述(说明) 效果展示
start 对齐单元格的起始边缘(靠左 或 靠上 对齐)
end 对齐单元格的结束边缘(靠右 或 靠下对齐)
center 单元格居中
stretch 拉伸,默认值,占满单元格的整个宽度或高度

2.8 设置隐式网格的列宽和行高(grid-auto-columns + grid-auto-rows)

  • 大家可以结合示例看着更清晰;
  • 显示网格
    • 就是我们使用 grid-template-columnsgrid-template-rows 属性中定义的行和列;
    • 简单来说,就是我们使用这两个属性定义了一个容器,是三行三列,这三行三列就是显示网格;
  • 隐式网格
    • 如果你在网格之外又放置了一些元素,或者是因为内容的数量改变而导致需要更多的网格轨道的时候,网格将会在隐式网格中创建行和列;
    • 简单来说,所谓的隐式网格就是超出我们规定行列之外的网格;
    • 就比如果说,我定义了一个三行三列的容器,容器里面放置了九个项目,我可以通过grid-auto属性设置其中的某几个项目跨行跨列显示(前提是行高设置的不是auto),这就会导致有些项目在当前这个容器中是没有位置放置的,会超出容器,显示在外边,我们将显示在外边的这些网格称为隐式网格;如果设置的行高为auto,他虽然不会超出容器,但是会改变网格轨道的数量,这也属于隐式网格;
  • 当有隐式网格出现的时候,就有新的问题,我们怎么给这些新出现的网格(隐式网格)设置列宽和行高呢?
    • 我们可以使用 grid-auto-columnsgrid-auto-rows 设置隐式网格的列宽和行高;
  • 🎯 在线代码演示 🎯
  • ❗❗ 注意
    • 如果是 新增列
      • 行高 是根据 grid-template-rows 指定的行高
      • 列宽 是根据 grid-auto-column 指定的列宽 ,若没有指定,则是由 由内容撑开(内容的宽度);
    • 如果是 新增行
      • 列宽 是根据 grid-template-columns 指定的列宽
      • 行高 是根据 grid-auto-row 指定的行高 ,若没有指定,则是由 由内容撑开(内容的高度);
  • 打开上面的在线代码,大家可以在 style 里面修改行高,看看行高定死和行高为auto的区别;
    • 行高固定:
      • 可能会出现新行(列同理);
    • 行高自适应:
      • 会压缩现有项目的行高(列同理);

三、网格项目属性介绍

3.1 ❌ 定位项目的位置(grid-column-start、grid-colmun-end、grid-row-start、grid-row-end)

  • 注意
    • 平时应该很少使用这些属性;
    • 使用 复合属性 grid-area进行替代(请看 3.2);
  • 作用
    • 指定网格项目所在的四个边框,分别定位在哪根网格线,从而指定项目的位置;

属性值介绍:

属性 说明 属性值
grid-row-start 指定在 哪一行 开始显示 网格元素 属性值见下表
grid-column-start 指定在 哪一列 开始显示 网格元素 属性值见下表
grid-row-end 指定 哪一行 停止显示 网格元素,或跨越多少行 属性值见下表
grid-column-end 指定 哪一列 停止显示 网格元素,或跨越多少列 属性值见下表
grid-column 复合属性 grid-column-start / grid-column-end;
grid-row 符合属性 grid-row-start / grid-row-end;

grid-row-start、grid-row-end 属性值介绍

描述
auto 按正常顺序排序
row-line 设置第几行 开始显示 / 停止显示 网格元素

grid-column-start、grid-column-end 属性值介绍

描述
auto 默认值,网格元素跨越一列
span n 指定网格元素将跨越的列数
column-line 指定从哪个列上 开始显示 / 停止显示 网格元素
  • 此处的代码演示请看下节;

3.2 ✅ 定位项目位置(grid-area)

  • 在说 网格容器的 grid-template-areas属性 的时候提过一嘴 grid-area属性,该属性可以 为网格元素 设置名称
  • 除了可以给网格元素设置名称之外,还可以设置从哪根网格线开始显示元素,到哪根网格线停止显示元素;
  • 该属性也可以单独使用;
  • 该属性是 3.1 小结中四个属性的复合属性;

语法:

  • grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end | itemname;
描述
grid-row-start 指定在 哪一行 开始显示 网格元素
grid-column-start 指定在 哪一列 开始显示 网格元素
grid-row-end 指定 哪一行 停止显示 网格元素,或跨越多少行
grid-column-end 指定 哪一列 停止显示 网格元素,或跨越多少列
itemname 指定网格元素名称
  • 🎯 在线代码演示 🎯

    css 复制代码
    /* 指定 two项目 的位置 */
    /* 从第一根行网格线开始 */
    /* 从第二根列网格线开始 */
    /* 从第二根行网格线结束 */
    /* 从第四根列网格线结束 */
    .two {
      grid-area: 1 / 2 / 2 / 4;
    }
    
    /* 指定 four项目 的位置 */
    /* 从第二根行网格线开始 */
    /* 从第二根列网格线开始 */
    /* 从第四根行网格线结束 */
    /* 从第三根列网格线结束 */
    .four {
      grid-row-start: 2;
      grid-column-start: 2;
      grid-row-end: 4;
      grid-column-end: 3;
    }

3.3 justify-self、align-self、place-self

  • justify-self 属性设置单元格内容的水平位置(左中右),与 justify-items属性的用法完全一致,但只作用于单个项目;
  • align-self 属性设置单元格内容的垂直位置(上中下),与 align-items属性的用法完全一致,但只作用于单个项目;
  • place-self属性 是 上述两个属性的复合属性 先 justify-selfalign-self
  • 上述属性的属性值是一样的:start(对齐单元格的起始边缘) | center(居中) | end(对齐单元格的结束边缘) |stretch(默认值,拉伸,占满整个单元格)

四、总结

  • grid布局也不一定是要学习的,flex布局也很方便,使用网格布局的话,还要考虑一些浏览器的兼容,但是学了,会了肯定是要比别人强一点点的好吧,一个字就是干😁😁;
  • 如果想要设置网格项目里面内容的对齐方式,我自己更喜欢将网格项目定义为弹性容器,两种布局方式结合使用,使用flex更加顺手😂😂;
  • 后续有时间了,会补充一点网格布局相关的代码(小demo);
相关推荐
浮华似水7 分钟前
Yargs里的Levenshtein距离算法
前端
_.Switch40 分钟前
Python Web 架构设计与性能优化
开发语言·前端·数据库·后端·python·架构·log4j
libai42 分钟前
STM32 USB HOST CDC 驱动CH340
java·前端·stm32
Java搬砖组长1 小时前
html外部链接css怎么引用
前端
GoppViper1 小时前
uniapp js修改数组某个下标以外的所有值
开发语言·前端·javascript·前端框架·uni-app·前端开发
丶白泽1 小时前
重修设计模式-结构型-适配器模式
前端·设计模式·适配器模式
程序员小羊!1 小时前
UI自动化测试(python)Web端4.0
前端·python·ui
破z晓2 小时前
OpenLayers 开源的Web GIS引擎 - 地图初始化
前端·开源
维生素C++2 小时前
【可变模板参数】
linux·服务器·c语言·前端·数据结构·c++·算法
vah1012 小时前
python队列操作
开发语言·前端·python