网格
网格是一个成熟的设计工具,许多现代网站布局是基于规则网格。在本文中,我们将看看基于网格的设计,以及如何使用CSS来创建网格——两者都通过现在的工具,和刚刚开始在浏览器中可用的新技术。
什么是网格布局?
网格仅仅是由水平和垂直线集合创建的一个模式,我们可以根据这个模式排列我们的设计元素。它们帮助我们创建设计——在页面之间移动时元素不会跳动或更改宽度,从而在我们的网站上提供高一致性。 网格通常具有列(column),行(row),以及在每行和列之间的间隙——通常称为沟槽(gutter)。
定义一个网格
Grid(网格) 模块为 display 属性提供了一个新的值:grid。当你将任何元素的 display 属性设置为 grid 时,那么这个元素就是一个 网格容器(grid container),它的所有直接子元素就成了 网格项(grid items)。
让我们创建创建一个 3×3 的布局
html
<div class="game-board">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
.game-board div 是网格容器,而 .box div 是网格项。现在我们将通过 Grid 布局来实现 3×3 布局。
.game-board
{
display: grid;
grid-template-rows: 200px 200px 200px;
grid-template-columns: 200px 200px 200px;
}
```
在这里,还使用了其他两个属性。
grid-template-rows 属性允许我们指定网格中的行数及行的高度。
grid-template-columns 属性允许我们指定网格中的列数及列的宽度。可以指定任何单位的尺寸大小,包括像素,百分比和其他单位fr。
**fr 单位(等分)**
fr 是为网格布局定义的一个新单位。它可以帮助你摆脱计算百分比,并将可用空间等分。
例如,如果在网格容器中设置这个规则:grid-template-rows: 2fr 3fr,那么你的网格容器将首先被分成 2 行。然后将数字部分加在一起,这里总和为 5, 即 5 等分。
就是说,我们将有 2 行:第一排占据垂直空间的 2/5 。 第二排占垂直空间的 3/5 。
***我们使用 fr 代替 px***
.game-board
{
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
复制代码
这里特别需要注意的是: fr 单位是等分可用空间,或者说剩余空间。看个例子
复制代码
.game-board
{
grid-gap:2px;
display: grid;
width:300px;
height:200px;
grid-template-rows: 100px 1fr 1fr;
grid-template-columns: 1fr 50px 1fr;
}
复制代码
布局效果如图:
![](http://i2.51cto.com/images/blog/201811/05/f892ab4b4dd338c0697e57dff620aa02.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
你会看到 fr 单位是将 总的尺寸 减去 单元格明确尺寸后,在等分剩余空间。 grid-gap 是间隔
**repeat() 函数**
在某些情况下,我们可能有很多的列和行。在 grid-template 属性中指定每一个值可能会很乏味。幸运的是,有一个 repeat 函数,就像任何一个循环重复多少次输出某个给定值。它有两个参数。第一个是迭代次数,第二个是要重复的值。我们用 repeat 函数重写上面的例子。
.game-board
{
display: grid;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(3, 1fr);
}
等价于:
.game-board
{
display: grid;
grid-template-rows: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
**grid-template 属性**
grid-template 属性是 grid-template-rows 和 grid-template-columns 的简写语法。 这是它的语法:
grid-template: ro ws / co lu mns;
我们上面的例子使用这个简写语法后,看起来非常整齐。
.game-board
{
display: grid;
grid-template: repeat(3, 1fr) / repeat(3, 1fr);
}
```
示例HTML
<div class="game-board">
<div class="box">X</div>
<div class="box">O</div>
<div class="box">O</div>
<div class="box">O</div>
<div class="box">X</div>
<div class="box">O</div>
<div class="box">O</div>
<div class="box">X</div>
<div class="box">X</div>
</div>
CSS
.game-board
{
width: 600px;
height: 600px;
margin: 0 auto;
background-color: #34495e;
color: #fff;
border: 6px solid #2c3e50;
border-radius: 10px;
display: grid;
grid-template: repeat(3, 1fr) / repeat(3, 1fr);
}
.box
{
border: 6px solid #2c3e50;
border-radius: 2px;
font-family: Helvetica;
font-weight: bold;
font-size: 4em;
display: flex;
justify-content: center;
align-items: center;
}
效果如图:
定位网格项
假设我想将第 6 个框移到第 2 个框的位置。没有CSS网格,不改变 HTML 的情况下,这几乎是一个不可能的任务,至少对我而言。但是如果我们使用网格模块,改变网格中网格项的位置是一件轻而易举的事情。要将第6个框移到第2个框的位置,我们必须确切知道第2个框在哪里。通过网格线编号的帮助,我们可以很容易地找到这个位置。第二个方框位于第2条列网格线之后,第3条列网格线之前,第1条行网格线之下,第2条行网格线之上。现在我们可以使用以下属性将这些网格线编号分配到第6个框中:
grid-column-start
grid-column-end
grid-row-start
grid-row-end
前两个属性对应于垂直网格线,也就是列网格线的开始和结束。 最后两个属性是指水平网格线,也就是行网格线的开始和结束。 让我们分配正确的网格线编号来移动第 6 个框。
.box:nth-child(6)
{
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 2;
grid-column-end: 3;
}
```
![](http://i2.51cto.com/images/blog/201811/05/c70f42c1009e0bb6e326368d8e0d92c2.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
还有两个简写属性用于将行和列的开始网格线和结束网格线设置在一起。
.box:nth-child(6)
{
grid-row: 1 / 2;
grid-column: 2 / 3;
}
此外,还有一个grid-area属性是所有四个上述属性的简写属性。 它按以下顺序取值:
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
现在我们的例子可以写成这样
.box:nth-child(6)
{
grid-area: 1 / 2 / 2 / 3;
}
上面的代码行也可以进一步减少。正如您所看到的,这个框只占用一行和一个列,所以我们只需要指定行和列的起始线,而无需结束线的值
.box:nth-child(6)
{
grid-area: 1 / 2;
}
如果我们想要第6个框跨越两个框的区域呢? 这很容易通过将 column-end 值加 1 的办法来完成。
.box:nth-child(6)
{
grid-area: 1 / 2 / 2 / 4;
}
```
也可以使用 span 关键字和占据的 轨道数量,来代替指定 grid-row-end 和 grid-column-end 的结束网格线编号。 在这种情况下,第6个框是跨越 2 列和 1 行。
.box:nth-child(6)
{
grid-area: 1 / 2 / 2 / span 2;
}
```
例子HTML:
<div class="container"> <header></header> <nav></nav> <main></main> <aside></aside> <footer></footer> </div>
CSS
.container { display: grid; grid-template-rows: 1fr 5fr 1fr; grid-template-columns: 2fr 5fr 3fr; grid-template-areas: "header header header" "nav main aside" "footer footer footer"; grid-gap: .75em; background-color: #eee; width: 100vw; height: 100vh; }
header { grid-area: header; background-color: #9b59b6; }
nav { grid-area: nav; background-color: #3498db; }
main { grid-area: main; background-color: #2ecc71; }
aside { grid-area: aside; background-color: #f1c40f; }
footer { grid-area: footer; background-color: #1abc9c; }
效果如下:
![](http://i2.51cto.com/images/blog/201811/05/0e2754ab5a6a2f69cdbfa646035e6b4b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
***此外,我们还可以把flex(弹性盒子)与grid联合起来用,在此不多说***