比Flex好用的Grid | 青训营笔记

270 阅读7分钟

这是我参与第四届青训营笔记创作活动的第2天

前言

前几天老师在讲css布局提到grid,才突然回忆起以前做部落考核的一个特别适合用grid布局的部分,只不过当时我用的是flex。现在说起布局grid我相信重要程度比起flex不遑多让啊。除了兼容性方面,其余的方面都是很完美的。我相信随着技术的不断更替,兼容性已经不再是问题。那今天让我们来看看grid到底能够干啥吧。

什么是Grid?

大家应该已经了解Flex布局,而Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。

Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。

了解Grid 布局是什么之后,我们还需要了解一些基本概念。

基本概念

image.png


容器和项目

我们将采用网格布局的区域,称为"容器"(container)。容器内部采用网格定位的子元素,称为"项目"(item)。

<div class="container">
    <div class="item"><span>1</span></item>
    <div class="item"><span>2</span></item>
</div>

上面代码中,最外层的<div>元素就是容器,内层的三个<div>元素就是项目。我特地将用类名将其形象化了。

不过有一点需要注意一下,项目只能是容器的顶层子元素,不包含项目的子元素,比如上面代码的<span>元素就不是项目。Grid 布局只对项目生效。

行和列

容器里面的水平区域称为"行"(row),垂直区域称为"列"(column)。

单元格

行和列的交叉区域,称为"单元格"(cell)。 正常情况下,n行和m列会产生n x m个单元格。比如,3行4列会产生12个单元格。

网格线

划分网格的线,称为"网格线"(grid line)。水平网格线划分出行,垂直网格线划分出列。 正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线,比如三行就有四根水平网格线。

image.png
上图是一个 4 x 4 的网格,共有5根水平网格线和5根垂直网格线。 一般而言,是从左到右,从上到下,1,2,3 进行编号排序,从右到左,从下到上,则是按照 -1,-2,-3…顺序进行编号排序。

好了,基本概念介绍的差不多了,接下来进入容器属性

容器属性

grid-template-*

容器指定了网格布局以后,接着就要划分行和列。grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高。

   grid-template-rows100px 100px 100px 100px (表示四行)

如上文所示,想写多少行或多少列,就填写相应属性的个数。

我们可以看到,上面代码后面的数值都相同,那有没有什么办法能不写那么多重复的东西呢?答案是可以的!

1、这里就不得不提到repeat()repeat()的第一个参数是重复的次数,第二个是重复的值。那么上面的代码可以写为:

   grid-template-columns:repeat(4100px

还有一个问题是,如果我们不填写,那会是什么结果呢?答案是自动分配,将容器自动充满。

2、 这就依赖于auto-fill 。有时,单元格的大小是固定的,但是容器的大小不确定,auto-fill属性就会自动填充 。还是用上边的例子,我们可以这么写:

   grid-template-columns:repeat(auto-fill,100px)

3、我们还能用fr方便表示比例关系 (fraction的缩写,片段的意思)

   grid-template-columns:repeat(41fr)//宽度平均分为四列等分

4、如果我们想控制极值,那就可以用到minmax() ,它将产生一个长度范围,2个参数,一个最小值,一个最大值

   grid-template-columns:1fr minmax(150px,1fr)

 最小都不会小于150px

5、如果是三列布局且中间一列想自适应,那就可以用auto 表示由浏览器自己决定长度

   grid-template-columns:100px auto 100px  (不写则默认auto

达到中间自动填充,根据浏览器的大小自动计算的效果。

6、网格线(作用:帮助定位 格子定位到哪跟线上,使用方括号,指定每一根网格线的名字,方便以后的引用)

   grid-template-columns[c1] 100px [c2] 100px [c3] // 2列3根网格线

row-gap / columns-gap

可以设置item 之间的距离,他们还可以缩写,用gap

    column-gap:20px  (列与列之间的距离)
    
    row-gap:20px  (行与行之间的距离)
    
    gap:20px 20px(合并简写,若省略了第二个值,则与第一个同值)

grid-template-areas

一个区域由单个或多个单元格组成 需要在项目属性里面设置,自己想怎么划分就怎么划分 一个格子可以成为一个区域 两个格子也可以成为一个区域

image.png


grid-auto-flow

划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。这个顺序由grid-auto-flow属性决定,默认值是row,即"先行后列"。也可以将它设成column,变成"先列后行"。

    grid-auto-flow:column;  //先列后行
    grid-auto-flow:column dense;//(用dense可以提高空间的利用率)

对齐方式

取值可以是:start | end | center | stretch

  1. 设置整个内容区域的水平垂直对齐方式

     justify-content:  center; 
     align-content: center;
    
  2. 设置所有单元格内容的水平垂直对齐方式

     justify-item: center; 
     align-item: center;
    

grid-auto-columns / grid-auto-rows

有时候,一些项目的指定位置,在现有网格的外部。比如我只设置了3×2个项目,但是实际有7个,此时就可以用这个属性来设置多出来的项目。

image.png

    .container { 
        display: grid; 
        grid-template-columns: 100px 100px 100px; 
        grid-template-rows: 100px 100px; 
        grid-auto-rows: 50px; //指定是50px
    }

如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。

项目属性

指定具体位置

比如要定位图中单元格1,我们可以这么写,有一点类似于用坐标确定矩形的意思[(1,1)(2,2)]

    grid-column-start:1;
    grid-column-end:2;
    grid-row-start:1;
    grid-row-end:2;

image.png

grid-area 

grid-area 指定项目在哪一个区域 (结合容器属性一起使用),比如图中的1所在项目

    grid-template-areas:'a a a'
                        'b b b'
                        'c c c'
    grid-area:b;

可简写为: grid-area:1/1/3/3; image.png


justify-self / align-self

只能用于单个项目(单元格)的水平/垂直方向

    justify-self:center;
    align-self:center;

简写:place-self:center  center

到此,记忆性的东西就告一段落了,接着就是应用了,感兴趣的伙伴不如还原一下以下的图,没错,就是以前我用flex写的那个。

实战

image.png 图来源于央视网

始终觉得,实践是最好的复习方式。最后的最后,谢谢大家这么厉害还来看我,如果发现问题或者需要补充的点麻烦大家通过评论告诉我。博取众长,共同进步!