34

Grid 布局是网站设计的基础,CSS Grid 是创建网格布局最强大和最简单的工具。

轻松使用 Grid 布局提高开发效率,对复杂的网页结构布局更加灵活。


一、概述

Grid 将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。网格是一组相交的水平线和垂直线,它定义了网格的列和行。我们可以将网格元素放置在与这些行和列相关的位置上。

我们比较熟悉的比如说坐标轴,坐标点;如果你看到上面这样一个网格首先想到是这不就是被淘汰的表格吗,表格之所以被淘汰最主要在性能方面,然而我们不得不承认表格对于整个网页的布局来说有一定的便利性。那么现在的网格布局就可以把表格里面的一些较好的方便的东西抽出来,然后把性能方面较差的地方去掉,所以说网格布局会成为将来互联网企业的一个热潮是有原因的。

网格布局的优势

固定的位置和弹性的轨道的大小

你可以使用固定的轨道尺寸创建网格,比如使用像素单位。你也可以使用比如百分比或者专门为此目的创建的新单位 fr来创建有弹性尺寸的网格。

元素位置

你可以使用行号、行名或者标定一个网格区域来精确定位元素。网格同时还使用一种算法来控制未给出明确网格位置的元素。

创建额外的轨道来包含元素

可以使用网格布局定义一个显式网格,但是根据规范它会处理你加在网格外面的内容,当必要时它会自动增加行和列,它会尽可能多的容纳所有的列。

对齐控制

网格包含对齐特点,以便我们可以控制一旦放置到网格区域中的物体对齐,以及整个网格如何对齐。

控制重叠内容

多个元素可以放置在网格单元格中,或者区域可以部分地彼此重叠。然后可以CSS中的z-index属性来控制重叠区域显示的优先级。

Grid vs Flexbox

Grid 布局与 Flex布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。Flex布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid布局远比Flex布局强大。不是说Grid布局取代Flex布局,实际上他俩可以很好的配合使用。

浏览器兼容

二、重要术语

网格容器(Grid Container)

元素应用display:grid;,它是其所有网格项的父元素。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>

把 container 元素变成一个 grid(网格),只要把其 display 设置为 grid。

CSS代码:

.container {
    display:grid;
}

网格项(Grid Item)

网格容器的子元素,下面的item元素是网格项。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>

网格线(Grid Line)

组成网格项的分界线。

记住:网格线仅仅是我们在定义网格容器的时候就产生的,跟我们的网格项没有直接的关联。网格线是我们在定义网格容器的时候伴随出来的虚拟的概念,也就是说在实际的HTML中是找不到这些线的。

网格轨道(Grid Track)

两个相邻的网格线之间为网格轨道。

网格轨道的特点是一定会顶到容器的边缘。
网格轨道必然跟网格项没有关联。

网格单元(Grid Cell)

两个相邻的列网格线和两个相邻的行网格线组成的是网格单元。

网格区域(Grid Area)

4个网格线包围的总空间。

三、容器中的属性

1、dislpay属性

display:grid | inline-grid | subgrid;

将元素定义为grid container,并为其内容建立新的网格格式化上下文(grid formatting context)。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>
.container {
    display:grid | inline-grid | subgrid;
}
  • grid:生成块级网格。
  • inline-grid:生成行内网格。
  • subgrid:如果网格容器本身是网格项(嵌套网格容器),此属性用来继承其父网格容器的列、行大小。
注意

当元素设置了网格布局,column、float、clear、vertical-align属性无效。
display:subgrid;目前所有浏览器都不兼容。

2、grid-template属性

1)grid-template-columns / grid-template-rows

使用以空格分隔的多个值来定义网格的列和行。

.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}
注意:此属性用在容器(container)上面。
  • 轨道大小 track-size: 可以使用css长度(px、em等)、百分比、或用分数(用 fr 单位)
  • 网格线名字 line-name:可以选择任何名字

2)grid-template-areas

通过引用 grid-area 属性指定的 网格区域(Grid Area) 名称来定义网格模板。

.container {
  grid-template-areas: none|
    "grid-area-name|. grid-area-name|. grid-area-name|. ..."
    "grid-area-name|. grid-area-name|. grid-area-name|. ..."
    "......";
}
  • grid-area-name:使用 grid-area 属性设置的网格区域的名称
  • ".":点号代表一个空网格单元
  • none:没有定义网格区域

例如:

.container {
  grid-template-areas: 
    "head head head head"
    "main main . sidebar"
    "foot foot foot foot";
}

以上例子强调以下几点:

第一:每一行都一定要用双引号括起来;

第二:每一个值对应一个网格单元,千万不要上面写了4个,下面只写三个,这样的话就会出问题;

第三:每个网格单元里的区域名称都以空格隔开;

第四:每个引号后面是没有任何逗号或封号,仅仅是回车换行。

grid-template

在单个声明中定义 grid-template-rows、grid-template-columns、grid-template-areas的简写。就个人而言,还是不要简写,因为简写之后可读性会变差一些。

.container {
  grid-template: none | subgrid | <grid-template-rows> / <grid-template-columns>;
}
  • none:将三个属性都设置为其初始值。所谓初始值默认为一行一列一个区域,也就是说回归到块元素本质,就是一个块。网格布局某些方面来说就是把我们的一个块给它用一种格子的形式把他区分为多个格子,也可以理解成是多个块。
  • subgrid:把 grid-template-rows 和 grid-template-columns 设置为subgrid,并且 grid-template-areas 设置为初始值。简单强调一下,第一:所谓的把行跟列设置为subgrid就是说还是得自己定义一下行和列,都自己定义了,就不必再简写了;第二:把网格区域定义为初始值,就是每个区域的大小都是一个网格单元,如果是这样其实就没必要去定义它。subgrid是目前为止所有浏览器都不兼容,那么在这里它依然适用,所以跟大家说一下:不推荐大家使用,只需了解知道即可。
  • grid-template-rows / grid-template-columns:把 grid-template-rows 和 grid-template-columns 设置为指定值,与此同时,设置 grid-template-areas 为none
.container {
  grid-template:
    [row1-start] "head head head" 25px [row1-end]
    [row2-start] "foot foot foot" 25px [row2-end]
    / auto 50px auto;
}

等同于

.container {
  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;
  grid-template-areas: 
    "head head head" 
    "foot foot foot";
}

不建议简写,避免混淆。

3、gap属性

grid-column-gap / grid-row-gap

指定网格线的大小,可以想象为设置列/行之间间距的宽度。也可以说是网格轨道之间的间距

.container {
  grid-column-gap: <line-size>;
  grid-row-gap: <line-size>;
}
  • line-size:一个长度值

grid-gap

grid-row-gap 和 grid-column-gap 的缩写。

.container {
  grid-gap: <grid-row-gap> <grid-column-gap>;
}
说明

起初是用 grid-gap 属性来定义的,目前逐渐被 gap 替代。
如果没有指定 grid-row-gap,则会被设置为与 grid-column-gap 相同的值。

4、items属性

justify-items

沿着行轴对齐网格内的内容。

.container {
  justify-items: start | end | center | stretch;
}
  • start:内容与网格区域的左端对齐
  • end:内容与网格区域的右端对齐
  • center:内容位于网格区域的中间位置
  • stretch:内容宽度占据整个网格区域空间(这是默认值)

align-items

沿着列轴对齐网格内的内容。

.container {
  align-items: start | end | center | stretch;
}
  • start:内容与网格区域的顶端对齐
  • end:内容与网格区域的底部对齐
  • center:内容位于网格区域的垂直中心位置
  • stretch:内容高度占据整个网格区域空间(这是默认值)

place-items

设置 justify-items 和 align-items 的简写形式。
注意:书写顺序为先列轴属性值后行轴属性值。

.container {
  place-items: center;
}

以上表示水平和垂直居中。

5、content属性

justify-content

设置网格容器内的网格沿着行轴对齐网格的对齐方式。

.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;    
}
  • start:网格与网格容器的左边对齐
  • end:网格与网格容器的右边对齐
  • center:网格与网格容器的中间对齐
  • stretch:调整 grid item 的大小,让宽度填充整个网格容器
  • space-around:在 grid item 之间设置均等宽度的空白间隙,其外边缘间隙大小为中间空白间隙宽度的一半
  • space-between:在 grid item 之间设置均等宽度的空白间隙,其外边缘无间隙
  • space-evenly:在每个 grid item 之间设置均等宽度的空白间隙,包括外边缘

align-content

设置网格容器内的网格沿着列轴对齐网格的对齐方式。

.container {
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}
  • start:网格与网格容器的顶部对齐
  • end:网格与网格容器的底部对齐
  • center:网格与网格容器的中间对齐
  • stretch:调整 grid item 的大小,让高度填充整个网格容器
  • space-around:在 grid item 之间设置均等高度的空白间隙,其外边缘间隙大小为中间空白间隙宽度的一半
  • space-between:在 grid item 之间设置均等高度的空白间隙,其外边缘无间隙
  • space-evenly:在每个 grid item 之间设置均等高度的空白间隙,包括外边缘

place-content

设置 align-content 和 justify-content 的简写形式。
注意:书写顺序为先列轴对齐属性值后行轴对齐属性值。

6、grid-auto属性

grid-auto-columns / grid-auto-rows

指定自动生成的网格轨道(又名隐式网格轨道)的大小。

隐式网格轨道

隐式网格轨道在显示的定位超出指定网格范围的行或列时被创建。也就是说网格项超出,一种是太多了,还有一种分两种情况:如果说仅仅因为太多的话,我们只需要控制行就可以了,列这一块的话肯定是跟着上面是一样的。但是有时列也会超出,超出情况会在讲到网格项的地方提到过,当网格项确定在网格单元或网格区域的时候是可以控制的,控制的时候除了网格区域的名字之外,它也可以通过地址条网格线来控制,但是这个线的名字如果是超过的时候就会出来,那么在这种情况下就会自动生成隐式网格轨道。

隐式网格轨道个人是不建议大家使用的,因为我们的这个隐式网格我们在容器当中一般来说我们在容器中统揽大局然后抠出局部,结果局部不由大局控制反而影响大局,这就有点反客为主,喧宾夺主的意思了,那在控制起来势必会有混乱,所以隐式网格轨道不是特别提倡大家使用。

.container {
  grid-auto-columns: <track-size> ...;
  grid-auto-rows: <track-size> ...;
}
  • track-size:可以是一个长度值,一个百分比,或者一个自由空间的一部分(使用 fr 单位)

grid-auto-flow

控制自动布局算法的工作方式。

.container {
  grid-auto-flow: row | column | row dense | column dense
}
  • row:告诉自动布局算法依次填充每行,根据需要添加新行 (默认)
  • column:告诉自动布局算法依次填充每列,根据需要添加新列
  • dense:告诉自动布局算法,如果后面出现较小的 grid item,则尝试在网格中填充空洞
注意:dense 只会更改网格项的可视顺序,并可能导致它们出现乱序,这对可访问性不利。

7、grid属性

在单个属性中设置所有以下属性的简写: grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, 和 grid-auto-flow 。

当然像左对齐、右对齐这些对齐方式等就不能简写在上面。就是说我们可以把多少行多少列以及它的区域还有隐式轨道以及他的布局方式都可以简写到 grid 里面并且同时将 sets grid-column-gap 和 grid-row-gap设置为他们的初始值,即使它们不能被此属性显示设置。

.container {
  grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
}
  • none:将所有子属性设置为其初始值。
  • grid-template-rows / grid-template-columns:将 grid-template-rows 和 grid-template-columns 分别设置为指定值,将所有其他子属性设置为其初始值
  • grid-auto-flow [grid-auto-rows [/ grid-auto-columns]]:接受所有与 grid-auto-flow,grid-auto-rows 和 grid-auto-columns 相同的值。如果省略 grid-auto-columns,则将其设置为 grid-auto-rows指定的值。如果两者都被省略,则它们被设置为它们的初始值
.container {
  grid: [row1-start] "head head head" 1fr [row1-end]
        [row2-start] "foot foot foot" 25px [row2-end]
        / auto 50px auto;
}

等价于:

.container {
  grid-template-areas: 
    "head head head"
    "foot foot foot";
  grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;    
}

简写形式就简单的做一个介绍,实际开发当中不建议简写形式。

四、CSS函数

  • repeat()
  • fit-content()
  • minmax()

1、repeat()

重复

跟踪列表的重复片段,允许大量显示重复模式的列或行以更紧凑的形式编写。

.container {
  grid-template-columns: repeat(repeat, values);
  grid-template-rows: repeat(repeat, values);
}
可用范围:这个函数可以用在 CSS Grid 属性 grid-template-columns 和 grid-template-rows。

重复次数

  • number:整数,确定确切的重复次数。
  • auto-fill:以网格项为准自动填充。
  • auto-fit:以网格容器为准自动填充。

  • length:非负长度。
  • percentage:相对于列轨道中网格容器的内联大小的非负百分比,以及行轨道中网格容器的块长度。
  • flex:单位为 fr 的非负维度,指定轨道弹性布局的系数值。
  • max-content:表示网格的轨道长度自适应内容最大的那个单元格。
  • min-content:表示网格的轨道长度自适应内容最小的那个单元格。
  • auto:作为最大值时,等价于 max-content。作为最小值时,它表示轨道中单元格最小长宽(由min-width/min-height)的最大值。

2、fit-content()

内容适配

根据公式min(最大大小、最大值(最小大小、参数))将给定大小夹紧为可用大小。

.container {
  grid-template-columns: fit-content([ <length> | <percentage> ]);
  grid-template-rows: fit-content([ <length> | <percentage> ]);
}

  • length:一个绝对的长度。
  • percentage:相对于给定轴上可用空间的百分比。

3、minmax()

长宽范围

定义了一个长宽范围的闭区间。

minmax([ <length> | <percentage> | <flex> | min-content | max-content | auto ],
[ <length> | <percentage> | <flex> | min-content | max-content | auto ]);

值(跟repeat的取值是一样的)

  • length:非负长度。
  • percentage:相对于列轨道中网格容器的内联大小的非负百分比,以及行轨道中网格容器的块长度。
  • flex:单位为 fr 的非负维度,指定轨道弹性布局的系数值。
  • max-content:表示网格的轨道长度自适应内容最大的那个单元格。
  • min-content:表示网格的轨道长度自适应内容最小的那个单元格。
  • auto:作为最大值时,等价于 max-content。作为最小值时,它表示轨道中单元格最小长宽(由min-width/min-height)的最大值。

例如:

.container {
  grid-template-columns: minmax(300px, 50px);
}

minmax()这个函数前面‘300px’是最小值,后面‘50px’是最大值,也就是说范围是从小到大的。当最小值大于最大值时,最大值将被忽略,整列会成为最小值。

五、网格项上的属性

  • start / end :规定每一个网格项在那个区域当中
  • grid-area:跟网格区域一样
  • self:自身里面的对齐方式
start / end 和 grid-area 两个属性都是规划出一个网格区域,把网格项放在一个网格区域里面,唯一不同的是 start / end 是通过网格线来规划出网格区域,而 grid-area 是通过网格区域在并列网格容器当中时就定义好的网格区域,然后直接来读取这个网格区域就可以了。

1、start / end 属性

grid-column-start / grid-column-end / grid-row-start / grid-row-end

使用特定网格线来确定 网格项(grid item)在网格内的位置。

.item {
  grid-column-start: <number> | <name> | span <number> | span <name> | auto
  grid-column-end: <number> | <name> | span <number> | span <name> | auto
  grid-row-start: <number> | <name> | span <number> | span <name> | auto
  grid-row-end: <number> | <name> | span <number> | span <name> | auto
}
属性值
  • line :可以是一个数字来指代相应编号的网格线,也可使用名称指代相应命名的网格线
  • span number :网格项将跨越指定数量的网格轨道
  • span name :网格项将跨越一些轨道,直到碰到指定命名的网格线
  • auto:自动布局,或者自动跨度,或者跨越一个默认的轨道
说明
  • 如果没有声明 grid-column-end / grid-row-end,默认情况下,该网格项将跨越1个轨道。
  • 网格项可以相互重叠。可以使用 z-index 来控制它们的堆叠顺序。

grid-column / grid-row

grid-column-start + grid-column-end 和 grid-row-start + grid-row-end 的简写形式。

.item {
  grid-column: <start-line> / <end-line> | <start-line> / span <value>;
  grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}

个人建议:斜杠前后的空格千万不要省略,有时可以识别,有时不可识别,对于浏览器来说小版本的话就会有差别。建议斜杠前后都要有空格。

属性值

start-line / end-line:每个值的用法都和属性分开写时的用法一样

例如:

CSS代码如下:

.container > .item:nth-child(1) {
    grid-column-start: 2;
    grid-column-end: 4;
    grid-row-start: 2;
    grid-row-end: 4;
}

等同于

.container > .item:nth-child(1) {
    grid-column: 2 / 4;
    grid-row: 2 / 4;
}

等同于

.container > .item:nth-child(1) {
    grid-column: 2 / span 2;
    grid-row: 2 / span 2;
}

2、grid-area 属性

网格区域

给 gird item 进行命名以便于使用 grid-template-areas 属性创建模板时来进行引用。

.item {
  grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
属性值
  • name :grid-template-areas 中定义的命名
  • row-start / column-start / row-end / column-end:可以是数字,也可以是网格线的名字
例如:

CSS代码如下:

.container > .item-a {
    grid-area: row1-start / 2 / 3 / five;
}

等同于

.container > .item-a {
    grid-column-start: 2;
    grid-column-end: five;
    grid-row-start: row1-start;
    grid-row-end: 3;
}

例如:

CSS代码如下:

.container > .item-a {
    grid-column: 2 / span 2;
    grid-row: 2 / span 2;
}

等同于

.container > .item-a {
    grid-area: 2 / 2 / 4 / 4;
}

3、self 属性

justify-self

沿着行轴对齐 grid-item 里的内容。

.item {
  justify-self: start | end | center | stretch;
}
属性值
  • start:将内容对齐到网格区域的左端
  • end:将内容对齐到网格区域的右端
  • center:将内容对齐到网格区域的中间
  • stretch:填充网格区域的宽度(这是默认值)

align-self

沿着列轴对齐 grid-item 里的内容。

.item {
  align-self: start | end | center | stretch;
}
属性值
  • start:将内容对齐到网格区域的顶部
  • end:将内容对齐到网格区域的底部
  • center:将内容对齐到网格区域的中间
  • stretch:填充网格区域的高度(这是默认值)

本篇文章到此结束,欢迎提建议哈!

参考文献:

https://developer.mozilla.org...

https://www.html.cn/archives/...


LeapFE
1.1k 声望2.3k 粉丝

字节内推,发送简历至 zhengqingxin.dancing@bytedance.com