CSS布局之Grid

1,916 阅读5分钟

网格布局(grid)

什么是网格布局?

​ 网格是由一系列水平及垂直的线构成的一种布局模式。根据网格,我们能够设计元素进行排列,帮助我们设计一些具有固定位置以及宽度的元素的页面,使我们的网站页面更加统一。

​ 一个网格通常具有很多的列(column)与行(row),以及行与行,列与列之间的间隙,这个间隙一遍被称之为沟槽(gutter)

定义一个网格

.wrapper {
	display: grid;
}
<div class="wrapper">
  <div>div1</div>
  <div>div2</div>
  <div>div3</div>
</div>

​ 与弹性盒子(flex)不同的是,定义网格布局后,网页不会马上发生变化,因为display:grid的声明,只是创建了一个只有一列的网格,所以你的子项还是会像正常布局流一样从上而下的一个个排列。

​ 为了让我们的容器看起来更像一个网格,我们可以给网格布局下的3个盒子定义一个宽度。

.wrapper {
  display: grid;
  grid-template-columns: 100px 100px 100px;
}

使用fr单位

​ 除了长度和百分比,也可以使用fr来定义网格的行与列的大小。这个单位表示可以可用空间的比例。

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

​ 缩放窗口,你会发现每一列的狂点可以随着可用空间的变小而变小。fr单位按比例划分了空间。

.wrapper {
	display: grid;
  grid-template-columns: 2fr 1fr 1fr;
}

​ 这样就使得第一列的空度是第二列和第三列的两倍。另外,fr还可以与其他的长度单位混合使用,比如:grid-template-columns: 200px 1fr 1fr;

网格间隙

​ 使用grid-column-gap属性定义列之间的间隙,使用grid-row-gap来定义行之间的间隙。使用grid-gap可以同时设定两者。

.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  grid-gap: 20px;
}

网格间隙距离可以任何长度单位,但是不能使用fr单位。

注意:*gap属性曾经有一个grid-前缀,不过后来的标准进行了修改,目的是让他们能够在不同的布局方法中都能起作用。尽管现在这个前缀不会影响语义,但为了代码的健壮性,你可以把两个属性都写上。

.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  grid-gap: 20px;
  gap: 20px;
}

重复构建行/列

​ 你可以使用repeat来重复构建具有某些宽度配置的某些列。举个例子,如果要创建多个等宽的列,你可以这样写。

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 20px;
}

​ 和之前的代码一样,你一样可以得到3个1fr的列。第一个传入repeat函数的值是3,表示后面列宽需要重复多少次,第二个值1fr表示需要重复的配置。

显示网格与隐式网格

​ 显式网格是我们用grid-template-columnsgrid-template-rows 属性创建的。而隐式网格则是当有内容被放到网格外时才会生成的。显式网格与隐式网格的关系与弹性盒子的main和cross轴的关系有些类似。

​ 隐式网格中生成的行/列大小是参数默认是auto,大小会根据放入的内容自动调整。当然,你也可以使用grid-auto-rowsgrid-auto-columns属性手动设定隐式网格的大小。下面的例子将grid-auto-rows设为了100px,然后你可以看到那些隐式网格中的行(因为这个例子里没有设定grid-template-rows,因此,所有行都位于隐式网格内)现在都是100像素高了。

.wrapper {
  display: flex;
  grid-template-columns: repeat(3 1fr);
  grid-auto-row: 100px;
  grid-gap: 20px;
}

​ 简单来说,隐式网格就是为了放显式网格放不下的元素,浏览器根据已经定义的显示网格自动生成的网格部分。

minmax()函数

​ 100像素高的行/列有时可能会不够用,因为时常会有比100像素高的内容加进去。所以,我们希望可以将其设定为至少100像素,而且可以跟随内容来自动拓展尺寸保证能容纳所有内容。显而易见,你很难知道网页上某个元素的尺寸在不同情况下会变成多少,一些额外的内容或者更大的字号就会导致许多能做到像素级精准的设计出现问题。所以,我们有了minmax函数。

minmax函数为一个行/列的尺寸设置了取值范围。比如设定为 minmax(100px, auto),那么尺寸就至少为100像素,并且如果内容尺寸大于100像素则会根据内容自动调整。在这里试一下把 grid-auto-rows 属性设置为minmax函数。

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-gap: 20px;
}

​ 编写完之后,我们可以在wrapper下的任意一个div中修改一些内容,使div的高度大于100px,然后观察变化。

基于线的元素位置

​ 在定义完了网格之后,我们要把元素放入网格中。我们的网格有许多分隔线,第一条线的起始点与文档书写模式相关。在英文中,第一条列分隔线(即网格边缘线)在网格的最左边而第一条行分隔线在网格的最上面。而对于阿拉伯语,第一条列分隔线在网格的最右边,因为阿拉伯文是从右往左书写的。

​ 我们根据这些分隔线来放置元素,通过以下属性来指定从那条线开始到哪条线结束。

  • grid-column-start

  • grid-column-end

  • grid-row-start

  • grid-row-end

    ​ 这些属性的值均为分隔线序号,我们也可以用以下缩写形式来同时指定开始与结束的线。

  • grid-column

  • grid-row

注意: 开始和结束的符号要使用/隔开。