加载中...

深入了解 Grid 布局的响应式用法

深入了解 Grid 布局的响应式用法

关于 Grid 布局的详细属性介绍和使用方式,这篇阮一峰的 《CSS Grid 网格布局教程》 中有详尽的介绍,不再赘述,建议详细阅读。本文摘取了其中与响应式布局有关的内容,并结合业务实际,梳理列划分的技巧和坑点,帮助大家深入认识 grid 布局。

涉及到的高频 CSS 属性值可以说相对冷门但又极为常用。冷门是因为这些属性相比之下受众并不广泛,常用则是因为「响应式栅格布局」非常依赖这些属性。

grid-template-columns

定义了容器之后,需要划分行和列。一般来说,行的划分(row)不需要关心,自然向下堆砌即可;而列(column)的划分受到容器宽度限制,它决定了一行能容纳多少个项目,也间接决定了总行数,是影响布局的关键因素

常见的列划分形式如下:

CSS
复制代码
.container { display: grid; grid-template-columns: 33.33% 33.33% 33.33%; // 百分比宽度 grid-template-columns: 100px 100px 100px; // 固定宽度 grid-template-columns: auto 50px auto; // 自动宽度(auto) grid-template-columns: 150px 1fr 2fr; // 比例宽度(fr) }

其中涉及百分比宽度、固定宽度、自动宽度(auto)、比例宽度(fr)。

auto 自动宽度

auto关键字表示由浏览器自己决定长度,常见用法如下:

CSS
复制代码
grid-template-columns: 100px auto 100px; // 第二列的宽度 = 总宽度 - 100px - 100px grid-template-columns: 100px auto auto; // 多个 auto 将会平分剩余空间

多个 auto 关键字将会「平分」剩余空间,如果我们想要按比例划分剩余空间呢?好办,用fr关键字。

fr 比例宽度

为了方便表示比例关系,grid 布局提供了fr关键字(fraction 的缩写,意为"片段")。

如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。下面代码表示两个宽度相等的列

CSS
复制代码
grid-template-columns: 1fr 1fr; grid-template-columns: 2fr 2fr; grid-template-columns: 3fr 3fr; ...

聪明的你一定发现了,在等比例划分的情况下,frauto的行为是一致的,上面的布局还可以这样:

CSS
复制代码
grid-template-columns: auto auto;

fr也可以与固定宽度结合使用,这时会非常方便。下面代码表示,第一列的宽度为 150px,第二列和第三列按照 1:2 分配剩余空间。

CSS
复制代码
grid-template-columns: 150px 1fr 2fr;

好奇的你一定想问,auto 是否可以和 1fr 混用达到平分的目的呢?答案是,不可以。

CSS
复制代码
grid-template-columns: auto 1fr 1fr auto; // 会变成什么样子?

如下,auto列将会被尽可能挤压直到最小宽度,而 fr 行为不受影响,依旧是按比例分割剩余空间。

New Image

通常不会这样使用,除非你真的有这样的需要。

repeat

重复写同样的值非常麻烦,尤其网格很多时。这时,可以使用repeat()函数,简化重复的值。

使用方式:repeat(重复的次数, 重复的值)。

重复的次数可以是

CSS
复制代码
grid-template-columns: repeat(3, 100px); // 固定次数重复 grid-template-columns: repeat(auto-fill, 100px); // 根据宽度自动计算重复次数

重复的可以是

CSS
复制代码
grid-template-columns: repeat(3, 33.3%); // 百分比重复 grid-template-columns: repeat(3, 100px); // 固定值重复 grid-template-columns: repeat(3, 1fr); // 比例重复 grid-template-columns: repeat(3, 50px 1fr 2fr); // 模式重复 grid-template-columns: repeat(3, minmax(100px, 1fr)); // 响应式重复

repeat()通常配合 minmax()、auto-fill等属性使用,可以实现各种灵活的响应式布局。

响应式布局

auto-fill

有时,单元格的宽度是固定的,但是容器的宽度不确定,会随着窗口宽度的变化而变化。

如果希望每一行容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充。

CSS
复制代码
grid-template-columns: repeat(auto-fill, 100px);

New Image

但我们可以明显看到,在剩余空间不足一个单元格宽度时,会出现空隙并不美观。为了解决这个问题,我们可以加入minmax函数,使单元格宽度在一定范围内浮动。

minmax

产生一个长度范围,表示长度就在这个范围之中。

使用方式:minmax(最小值,最大值)

下面代码中,minmax(150px, 1fr)表示列宽不小于150px,不大于1fr。

换句话说,当宽度小于 100px 时,该值实际为 150px,当宽度大于 1fr 时,该值为 1fr

CSS
复制代码
grid-template-columns: 1fr 1fr minmax(150px, 1fr);

New Image

可以看到,第三列的宽度大于 150px 时宽度为 1fr,并随之变化;当宽度小于150px 时,固定为 150px。

🎉 auto-fill & minmax

没错,聪明的你一定想到了。既然 auto-fill 配合 repeat 可以尽可能填充单元格列,minmax 又能提供一个浮动范围。那我们只需要将二者结合起来,

CSS
复制代码
grid-template-columns: repeat(auto-fill, minmax(100px, auto)); grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); // 等价

就能打造出下面这样的响应式效果,而这也是我们业务中最常用的栅格布局样式👇🏻:

New Image

按照上面的公式模板,我们只需要为单元格设置一个基准宽度即可(如:100px),其他由浏览器负责计算。

QA

为什么会出现横向滚动条?

根据最新标准,grid-column-gapgrid-row-gapgrid-gapgrid- 前缀已经删除。

在实践中,我们通常会配合其他属性,如 gap 属性,一同使用,划分单元格之间的间距。

下面的代码设置了 gap: 20px; 表示一行有 3 列,3 列均分占满 1 行,在此基础上还要留出 2 * 20px 的空隙,作为单元格之间的间隔。

CSS
复制代码
.container { display: grid; overflow: auto; grid-template-columns: repeat(3, 33.33%); gap: 20px; }

很明显,这样的布局一定会出现滚动条,且间距(gap)越大,滚动条越明显。因为三列已经占满了一行,没有多余的空间分配给 gap 了。如下所示,可以看到明显的滚动条:

New Image

如果想在实现 3 列均分且占满效果的同时,还想拥有间隙,可以这样:

CSS
复制代码
gap: 20px; grid-template-columns: repeat(3, auto); grid-template-columns: repeat(3, 1fr); // 或

当然,如果你愿意,根据需要使用 minmax 也是可以的,而我们上方提到的响应式布局,更是天然支持这样布局。


看到这里的你很有前途,不如点个赞吧~