Grid 布局又叫作网格布局,顾名思义是一种基于二维网格的布局方式,Grid 的强大使人兴奋,让咱们一块儿来走进 Grid 的世界吧。css
好了,你们都坐好,我准备发车啦。不符合要求的同窗请下车,没满 18 岁的,咳咳,开玩笑。不是全部人如今都能搭上 Grid 的小车车,毕竟项目兼容性问题很现实,不过不耽误咱们学习。html
我替你们翻译一下上面的浏览器都是啥,顺序从左到右:css3
好了,你们看了看浏览器的兼容性就知道,现在主流浏览器都已经支持了 Grid 布局,还等啥呢?上车吧。git
乘客们,在开始了解用法以前,咱们要了解一些 Grid 布局的基本概念,我想你们应该小时候都用过一种叫小字本的东西,这就是个正儿八经的网格。github
display: grid;
就将一个容器变成了网格容器,就好比说上面小字本里外层的那个绿框。好了,基本概念了解的差很少了,咱们去往下一站。segmentfault
第二站到了,咱们要继续吹牛了。api
本站要介绍的 api:浏览器
grid-template-columns
和 grid-template-rows
grid-gap
-> grid-row-gap
+ grid-column-gap
第一件事,掏出代码:ide
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
复制代码
body {
background: #CCCCCC;
}
.container > div {
font-size: 35px;
font-weight: bold;
color: #fff;
text-align: center;
background: #666666;
}
.container > div:nth-child(2n) {
background: #336666;
}
.container > div:nth-child(4n) {
background: #f37e70;
}
.container {
display: grid;
grid-template-columns: 120px 120px 120px;
grid-template-rows: 50px 50px;
}
复制代码
好了,如今它长这个样子。函数
咱们能够看出上面一些关键的 css 代码:
display: grid;
将外层容器变成一个网格布局容器。grid-template-columns: 120px 120px 120px;
将容器画成 3 列,每列 120px;grid-template-rows: 50px 50px;
画成 2 行,每行 50px。上面两个 api 给网格加上了两条横线,三条竖线,把容器画成了一个个的格子。而后将网格项一个一个填进去,那么聪明的同窗又会想了,你这样画好格子,里面有 6 个格子,那我再添一个 div 会出现什么状况?好吧,知足这位同窗的好奇心,咱们加一个 div 进去。
而后就会变成这样:
神奇,是否是,明明俺就画了 6 个格子,竟然 7 出现了,而且还有必定高度。其实在 grid 里,它有一个隐式网格轨道。
当咱们的网格项处于咱们没有定义的网格部分的时候,它会有一个默认的值,咱们也能够选择去定义隐式网格轨道的大小,经过 grid-auto-rows
和 grid-auto-columns
来定义行和列,关于这部分要说的话不少,你们能够到这个博客去了解。
讲完这个,咱们再看看,每一个格子挨得太近了,一点都不美观,咋办呢?咱们加上 grid-gap: 2px 4px;
看看:
能够看到,使用这个属性咱们定了网格的间隙,这个 api 实际上是两个 api 的组合(grid-column-gap
和 grid-row-gap
)。
好了,这一站就是基本用法,下面咱们继续发车啦。
上面咱们经过一些基础的属性,写了一个 6 个格子的页面。这一节咱们不讲属性,讲一下在 grid 中的一个单位值 — fr。那么这个 fr,表明的是什么意思呢?在 flex 中也有相似的属性,fr 的意思就是在自由空间进行分配的一个单位,那么是什么意思呢?
好比说,容器宽度为 1000px,如今假如 grid-template-columns: 200px 1fr 1fr 2fr
。那么这就表示分了 4 列,第一列为 200px,而后剩下的 800px 就是自由空间了,通过计算能够得出 1fr 为 200px,这就是 fr 的意义。
那么,咱们上面的例子其实能够这样写 grid-template-columns: 1fr 1fr 1fr;
。可是如今又出现了一个问题,这个 1fr 写的好烦,能不能就写一个。
好消息,是有的,咱们可使用 repeat 来简写,因而上面的例子又能够改为 grid-template-columns: repeat(3, 1fr)
。
说完这两个,咱们继续下一站。
这一站咱们要说这些 api:
grid-column
-> grid-column-start
+ grid-column-end
grid-row
-> grid-row-start
+ grid-row-end
好了咱们抛弃上面的例子,如今假如咱们接到一个需求,咱们要使用 3 栏布局,左右固定 200px,中间自适应,咋办呢?相信你们一下就想到了,毕竟你们都很聪明。
<div class="container">
<div>Left</div>
<div>Main</div>
<div>Right</div>
</div>
复制代码
// ...,跟上面相同的代码
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 500px;
grid-gap: 2px 4px;
}
复制代码
好了,如今咱们是这样的:
需求又来了,咱们要加上一个 header 和一个 footer,宽度是 main 的宽度,如今又怎么办呢?首先 container 须要改:
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 100px 500px 100px;
grid-gap: 2px 4px;
}
复制代码
如今咱们能够用网格线来进行布局了,在上面的网格布局中横向有 4 条网格线,竖向有 4 条网格线,默认网格会为编号,从 1 开始,因而咱们能够用网格线将元素固定到它应该在的位置:
/* 类名就是 html 对应的 div */
.left {
grid-column: 1 / 2;
}
.main {
grid-column: 2 / -2;
}
.right {
grid-column: -2 / -1;
}
.header {
grid-column: 2 / -2;
}
.footer {
grid-column: 2 / -2;
}
复制代码
这样的话,咱们的布局就成了这样子:
在上面有一个小技巧,若是中间线比较多,你要选择比较靠后的线,就可使用负数来进行选择。
上面的 1 和 2 的使用是差很少的,这里就不详述了。
注意,你能够给网格线取一些语义化的名字便于你使用,好比下面这样,footer 同样能够和 main 等宽:
<div class="container">
<div class="left">Left</div>
<div class="main">Main</div>
<div class="right">Right</div>
<div class="footer">Footer</div>
</div>
复制代码
.container {
display: grid;
grid-template-columns: 200px [main-start] 1fr [main-end] 200px;
grid-template-rows: 200px 200px;
grid-gap: 2px 4px;
}
.footer {
grid-column: main-start / main-end;
}
复制代码
咱们能够给网格线取名字,而后再去使用它。
这节介绍的 api:
咱们能够经过另外一种建立网格的方式来定位元素,就如同画图同样,就那上面那个有 header 和 footer 的例子来讲,咱们能够这么写:
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 50px 300px 50px;
grid-template-areas:
". h ."
"l m r"
". f .";
grid-gap: 2px 4px;
}
.header {
grid-area: h;
}
.left {
grid-area: l;
}
.right {
grid-area: r;
}
.main {
grid-area: m;
}
.footer {
grid-area: f;
}
复制代码
经过这样的方式,咱们同样能作到上面的那种定位操做,注意的是在 grid-template-areas
中 . 表明的是这个位置空着。
在上面,咱们说过一种 repeat 的简单用法,建立网格时重复指定的次数,可是有的时候咱们并不想指定次数,而是但愿自动填充,这时候怎么办呢?
这时候咱们就要提到 auto-fit
和 auto-fill
了。
首先,咱们经过 repeat 先把格子建出来:
.container {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: 50px;
grid-gap: 2px 4px;
}
复制代码
这样咱们就建立了一个基于 9 列的网格系统,若是咱们的视窗不断变小,那么咱们的每一格也会相应的变窄,咱们不但愿它变得很是窄,咋办呢?
Grid 有一个 minmax() 函数可使用,这个函数接收两个参数,一个最小值,一个最大值,当浏览器窗口发生改变的时候,它可以保证该元素是在这个范围以内改变。好比说:
.container{
grid-template-columns: repeat(9, minmax(250px, 1fr));
}
复制代码
当咱们把 grid-template-columns
变成这样以后,每一列的宽度都会在 250px 到 1fr 之间,可是咱们会发现,他装不下这些格子,可是它也没有换行,由于你告诉它有 9 列,因而出现了滚动条,可是你不但愿出现这东西,咋办呢?
这时候就到了咱们上面说的两个参数出场的时候到了。
.container{
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
复制代码
当咱们加上这个参数事后,就会让浏览器去处理列宽和换行的问题,若是你给的容器宽度不够,它就会换行。
那么 fit 和 fill 有啥区别呢?我找了一些资料,里面有两句总结是这么说的:
auto-fill
倾向于容纳更多的列,因此若是在知足宽度限制的前提下还有空间能容纳新列,那么它会暗中建立一些列来填充当前行。即便建立出来的列没有任何内容,但实际上仍是占据了行的空间。
auto-fit
倾向于使用最少列数占满当前行空间,浏览器先是和 auto-fill 同样,暗中建立一些列来填充多出来的行空间,而后坍缩(collapse)这些列以便腾出空间让其他列扩张。
作一个实验,当宽度足够大时,这二者区别就出来了:
.container1{
grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
}
.container2{
grid-template-columns: repeat(auto-fit, minmax(40px, 1fr));
}
复制代码
这样能够看出区别了,fill 是尽量多容纳列,它会本身造一些列来填充剩余空间,其实它是铺满了的,只是你看不见而已,而 fit 是扩张原有列来铺满这一行。
至于具体详细的解释,你们能够去这篇译文看一看,说得很是详细了。
好了,关于 grid 大概就说这么多了,其实关于这些 api 的使用还有不少的参数问题,这里没有细说,只是让你们知道 grid 能干吗,至于详细的说明,能够去下面几个博客看一看。
另外还有一些属性没有介绍,是关于对齐等属性,你们在有需求的时候能够去下面的资料找到。
更多资料:
若是各位看官看的还行,能够到 个人博客仓库 里给我一颗小小的 star 支持一下,不胜感激。