当前位置: 华文世界 > 科技

从零开始的Grid布局掌握

2024-09-04科技

前言

在上一篇文章中,我们了解了 Flex 布局系统的强大功能和灵活性,其能够帮我们轻松地控制和对齐页面中的元素

然而,在实际的网页设计中,我们经常会遇到更加复杂的布局需求,例如创建多列、多行的网格结构,为了解决这些需求, Grid 布局应运而生

Grid 布局是一种 二维 布局系统,它不仅能够像 Flex 一样处理单轴上的布局,还能同时处理 行和列 ,从而实现更加复杂和精确的布局控制,无论是简单的页面排版,还是复杂的网页设计, Grid 布局都能提供强大的支持

Grid布局

Grid 布局,也称 网格布局 ,不同于 Flex 针对轴线的 一维布局 Grid 是一个 二维 的布局,其将 项目 划分在 中, 容器 就像一个 网格 一样, 项目 就是一个个单元格,其能实现实现更加精细和复杂的设计

Grid 布局是由W3C在 2011 年首次提出的,于 2014 年,发布了关于首个工作草案

2016 年, Grid 布局规范进入候选推荐阶段,最终在 2017 年,正式成为W3C推荐标准,并在主流浏览器中得到了广泛支持

其兼容性如下(主流浏览器均已支持):

基本概念

任何元素均可定义为 Grid 容器,使用 Grid布局 ,只需设置元素的 display 属性为 grid 或 inline-grid 即可,如下:

定义了 Grid 布局的元素,称为 容器 (container),其直接子元素会自动按 网格 排列,称为 项目 (item)

注意,设Grid后,容器内项目的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效

行和列

容器 内水平区域称为 ,垂直区域称为

交叉的区域称为 单元格 项目 就按顺序存放在一个个单元格内

网格线

划分单元格的线称为 网格线 ,水平的网格线划分 ,垂直的网格线划分

区域

由一个或多个 项目 组成的矩形区域称为 Grid区域 (grid areas)

容器属性

下列属性主要使用于 容器

grid-template-rows|columns

该属性主要用于定义 网格 (几行,各行宽;几列,各列宽等)

其是 grid-template-rows 和 grid-template-columns 属性的简写形式,形式如下:

grid-template-rows 属性定义每一行的行宽, grid-template-columns 属性定义每一列的列宽

如下,定义一个3×3的 Grid容器 ,且每个 项目 的宽高均为 100px

有时,我们并不能确定某行(列)的宽度,或行(列)数量较多时,按这种形式写比较复杂,所以,CSS提供了一些 函数 关键字 ,可方便我们的设置

  • repeat()
  • 函数 用于 简化重复值 ,形式如下:

    效果与上侧实现一致

    repeat()接收两个参数,第一个参数表示 重复的次数 ,第二个参数表示 重复的内容

  • fr
  • 关键字 主要用于表示 比例 关系,其为 fraction (片段)的缩写

    上侧container-1表示,将 容器 均分为三列,container-2表示,将 容器 按1:2:3的比例分为三列

  • minmax()
  • 函数 用于表示一个 长度范围 ,其接收两个参数:一个最小值(min)和一个最大值(max),表示长度在 [min, max] 内,数值是任何有效的CSS长度值、百分比或 auto

    上侧代码表示将 容器 分为三列,左右两列固定宽度,中间的列最小宽度不小于 72px ,最大宽度不大于 1fr

  • auto
  • 关键字 表示由浏览器自己决定长度

    上侧代码中,第一列会占据 容器 剩余宽度,除非列内单元格内容设置了 min-width ,且这个值大于最大宽度

  • auto-fill
  • 关键字 用于实现 自动填充 ,有时候, 项目 (单元格)的大小是确定的,但 容器 的大小不确定,因此我们无法确定每一行(列)可容纳的 项目数 ,此时,我们希望每一行(列)可以尽可能多地容纳 项目 ,即可用 auto-fill

    上侧的代码,我们对 设置了 auto-fill ,此时 容器 会按每列 100px 的宽度,自动填充列,直到不可容下更多 为止

    与 auto-fill 类似的,还有一个 auto-fit 关键字

    auto-fill与auto-fit的区别:

    auto-fill会在 容器 中尽可能多地填充列或行,不管 单元格 是否有内容

    特点 为:

    自动填充列或行,尽量多地创建网格轨道

    即使某些网格单元没有内容,也会分配空间

    auto-fit当 容器 宽度增加时,会调整现有列的大小,而不是增加新的空列

    特点 为:

    自动适应列或行,现有列会根据容器大小调整

    空列会被折叠,不占用额外的空间

    一般情况下,两种基本无差别,只有当 容器 足够宽,足以在一行容纳所有 单元格 ,并且单元格宽度 不固定 ,才会有差异

    举个栗子

    容器 宽度足够富余时,fill 容器 会尽可能多地容纳列,每列100px,而fit容器会优先分配空间给已有列,每列 1fr

  • 网格线的名称
  • Grid 布局内,允许指定每一根网格线的名字,方便以后的引用

    主要方式为使用 方括号 ,在 grid-template-columns 属性和 grid-template-rows 属性里面定义,如:

    上侧代码中,定义了一个 3×3 的网格,所以有 4 根列线与 4 根行线,上侧的[]内的值即为每根线的名称,如: c1

    同一根线可以有多个名称,只需定义在同一个 方括号 内,用 空格 隔开,如: [c1 column1]

    gap

    该属性用于定义 行与行 之间、 列与列 之间的 间距 ,是 row-gap 和 column-gap 的简写,形式如下:

    接收一个或两个值,当只有一个时,表示行列间距均为该值

    row-gap 属性用于设置 行与行 之间的间距

    column-gap 属性用于设置 列与列 之间的间距

    上侧代码大致效果如下(橙色部分即为间距):

    过去的 gap 名称为 grid-gap ,该名称首次于 2017 年在 CSS Grid Layout Module Level 1 中被引入,但在 2018 年提出的 CSS Box Alignment Module Level 3 被重命名为 gap ,同时适用于Grid和Flex

    grid-template-areas

    该属性用于定义 网格区域 ,对网格区域进行 命名 ,后续可使用命名的网格区域进行布局,如:

    上侧代码定义了一个 3×3 的网格,共有 9 个单元格,分别命名为 a-i ,共有 9 个区域

    一个区域,可以由 一个或多个 单元格组成,当有多个单元格时,则用相同名称即可,如:

    相同名称的单元格会合并为一个区域

    如某些单元格不想命名,无需利用处理,用.点占位即可,如:

    上侧的代码命名了 4 个区域,中间的点表示该单元格不属于任何区域

    使用场景

    简单直观地定义一个页面的布局

    当你使用 grid-template-areas 定义网格区域时,Grid会自动生成与这些区域名称相关的命名网格线

    命名网格线的格式如下:

    area-name-start:区域的起始线

    area-name-end:区域的结束线

    例如,如果定义了一个名为 header 的区域,会自动生成以下网格线:

    header-start

    header-end

    grid-auto-flow

    该属性用于定义自动放置的 项目 的布局顺序,其决定了当 容器 中的 项目 没有明确指定位置时,浏览器如何自动放置它们,其可能值为:

  • row :( 默认值 )项目按照行的顺序放置
  • column :项目按照列的顺序放置
  • row dense :按行顺序放置项目,并尽可能紧凑地填充空白区域
  • column dense :按列顺序放置项目,并尽可能紧凑地填充空白区域
  • row 的放置顺序是 先行后列 ,即先放满第一行,再放第二行,效果如下:

    column 的放置顺序是 先列后行 ,即先放满第一列,再放第二列,效果如下:

    dense 用于与 row 或 column 搭配使用,使 容器 更 紧凑 地排列 项目

    如下,为无 dense 情况下的排列情况,会存在一些空白没有利用:

    当搭配 dense 后,空白会被尽可能地利用,情况如下:

    *-items

    justify-items 属性设置单元格内 项目 的水平对齐效果(左中右)

    align-items 属性设置单元格内 项目 的垂直对齐效果(上中下)

    两个属性均有如下取值:

  • stretch :( 默认值 )网格项在每个单元格中拉伸以填满单元格(如果可能)
  • start :网格项在每个单元格的起始位置对齐(左对齐)
  • end :网格项在每个单元格的结束位置对齐(右对齐)
  • center :网格项在每个单元格的中央对齐
  • 语法如下:

    place-items 属性是 align-items 属性和 justify-items 属性的合并简写形式,形式如下:

    接收两个值,用空格隔开,第二个值可省略,如省略,则表示与第一个值相同

    *-content

    justify-content 属性用于控制整个内容区域在 容器 内的水平对齐(左中右)

    align-content 属性用于控制整个内容区域在 容器 内的垂直对齐(上中下)

    两个属性取值均相同,如下:

  • start :内容在容器的起始位置对齐
  • end :内容在容器的结束位置对齐
  • center :内容在容器的中央对齐
  • stretch :内容在容器中拉伸以填满可用空间
  • space-between :内容行(列)之间平均分配空间,第一行(列)与容器的起始位置对齐,最后一行(列)与容器的结束位置对齐
  • space-around :内容行(列)之间的空间平均分配,每一行(列)周围的间距相等
  • space-evenly :内容行(列)之间以及内容与容器边缘之间的空间平均分配
  • place-content 属性是 align-content 属性和 justify-content 属性的合并简写形式,语法如下:

    如果省略第二个值,则会假定第二个值与第一个值相同

    grid-auto-*

    grid-auto-columns 和 grid-auto-rows 用于定义在 Grid 布局中隐式创建的列和行的大小

    其语法如下:

    <track-size> 可以是任何有效的 CSS 尺寸值,如 px 、 % 、 fr 、 auto 等

    举个栗子

    比如,我们创建了一个 3×3 的网格 容器 ,但我们的 项目 不止 9 个(比如有 11 个),或者有些项目指定位置超出 3×3 的范围(比如设置在 (4, 2) 位置),此时,浏览器会自动生成多余的网格,用于放置 项目

    在上侧代码中,任何隐式创建的行(即超过显式定义的三行的行)将被设置为 50px 高

    grid-template

    该属性是 grid-template-rows 、 grid-template-columns 和 grid-template-areas 的合并简写形式

    举个栗子

  • 第一行的高度为 100px ,第二行为 200px ,第三行为 100px
  • 第一列的宽度为 1fr ,第二列为 2fr ,第三列为 1fr
  • 定义了三个区域: header 、 sidebar 和 content
  • grid

    grid 是 grid-template-rows 、 grid-template-columns 、 grid-template-areas 、 grid-auto-rows 、 grid-auto-columns 、 grid-auto-flow 六个属性的合并简写形式

    基本语法

    简写形式可以简化书写,但同时也降低了代码可读性,不建议使用

    项目属性

    主要作用域 项目 上的属性

    grid-column|row

    grid-column 是一个简写属性,用于定义 项目 在网格中的水平位置,其结合了以下两个属性:

  • grid-column-start :定义项目的水平初始位置
  • grid-column-end :定义项目的水平结束位置
  • 基本语法

    <grid-line> 可以是行号、命名的网格线、 span 关键字加行数,或者 auto

    <grid-area> 是通过 grid-template-areas 定义的网格区域名

    grid-row 也是一个简写属性,用于定义 项目 在网格中的垂直位置,其结合了以下两个属性:

  • grid-row-start :定义项目的垂直初始位置
  • grid-row-end :定义项目的垂直结束位置
  • 使用与 grid-column 一致

    span 关键字,后接空格跟一个数字,表示跨越(占据)多少行(列)

    grid-area

    该属性用于指定 项目 放置在哪一区域

    基本语法

    <grid-area-name> 为 grid-template-areas 定义的区域名称

    其还有另一种语法:

    可用作 grid-row-start 、 grid-column-start 、 grid-row-end 、 grid-column-end 的合并简写形式

    *-self

    justify-self 属性用于设置 项目 在单元格内的水平对齐方式,跟 justify-items 属性的用法类似,但只作用于单个项目

    align-self 属性用于设置网格项目在单元格内的垂直对齐方式,跟 align-items 属性的用法类似,但只作用于单个项目

    两者可能取值均相同,如下:

  • stretch :( 默认值 )项目在单元格内拉伸以填满单元格
  • start :项目在单元格的起始边对齐
  • end :项目在单元格的结束边对齐
  • center :项目在单元格的中心对齐
  • place-self 是一个简写属性,用于同时设置 justify-self 和 align-self 的值,形式如下:

    如果省略第二个值,则第二个值与第一个值相等

    特点

    二维布局系统 :支持同时定义行和列,适合复杂布局

    显式与隐式网格 :可以明确定义网格,同时自动创建额外的网格以容纳项目

    强大的对齐与定位控制 :通过属性如 justify-items 、 align-items 、 justify-content 和 align-content ,可以精确控制项目在网格中的位置和对齐方式

    网格间距和分区 :支持定义网格之间的间距,并能够划分为命名的网格区域,便于布局管理和维护

    响应式设计支持 :可以轻松地调整网格的大小和布局,以适应不同的屏幕尺寸和设备

    配合 Flexbox 使用 :与 Flex 结合使用,可以实现更复杂的布局需求,灵活而强大

    使用场景

    复杂的布局需求 :适合需要精确控制多个项目在网格中位置和大小的复杂布局,如新闻网站的多栏布局或者仪表板的网格化布局

    网格化设计 :对于需要将页面划分为多个命名区域并对其进行管理的设计,如大型网页或应用程序的板块化设计

    响应式设计 :能够根据不同的屏幕尺寸和设备自动调整布局,使得设计在移动设备和桌面上都能够优雅地呈现

    比如,哔哩哔哩推荐的视频列表就是用 grid 实现的, Grid 是一个非常强大的布局工具,特别适合于需要更高级和复杂布局需求的现代网页设计和开发