grid布局了解一下

1,056 阅读9分钟

基本概念

首先,看一张图,了解一下容器和项目(不难理解,容器就是包在外层的元素,项目就是内部的元素) image.png

我们后面会介绍下图的内容

image.png

每个grid布局,都有隐藏的网格线,用来帮助定位的。 image.png

容器属性

行列分布

  • grid-template-columns
  • grid-template-rows

说明:想要多少行/列,就填写相应属性的个数。不填写自动分配

做些准备

我们先画好div,main中包着十个子元素。main此时就是容器(container),十个子元素就是项目(item)。我们给十个子元素加上不同的颜色

<html>
<head></head>
<style>
    .main {
        width: 600px;
        height: 600px;
        border: 10px solid skyblue;
    }

    .item {
        font-size: 50px;
        color:#FFF;
    }

    .item1 {
        background-color: rgb(164, 233, 231);
    }

    .item2 {
        background-color: rgb(117, 219, 153);
    }

    .item3 {
        background-color: rgb(145, 206, 54);
    }

    .item4 {
        background-color: rgb(190, 166, 218);
    }

    .item5 {
        background-color: rgb(208, 100, 169);
    }

    .item6 {
        background-color: rgb(221, 164, 114);
    }

    .item7 {
        background-color: rgb(68, 87, 174);
    }

    .item8 {
        background-color: rgb(17, 120, 117);
    }

    .item9 {
        background-color: rgb(230, 79, 79);
    }

    .item10 {
        background-color: rgb(68, 58, 204);
    }
</style>
<body>
    <div class="main">
        <div class="item item1">1</div>
        <div class="item item2">2</div>
        <div class="item item3">3</div>
        <div class="item item4">4</div>
        <div class="item item5">5</div>
        <div class="item item6">6</div>
        <div class="item item7">7</div>
        <div class="item item8">8</div>
        <div class="item item9">9</div>
        <div class="item item10">10</div>
    </div>
</body>
</html>

此时,我们没有添加任何布局。效果如下,可以看到,子元素都已经挤出了容器中。

image.png

grid-template-columns

给容器添加属性,布局为grid。设置了三列,每列的宽为100px。

    .main {
        width: 600px;
        height: 600px;
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: 100px 100px 100px;
    }

image.png

grid-template-rows

因为我们有四行,然后我们每行都给100px

    .main {
        width: 600px;
        height: 600px;
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: 100px 100px 100px;
        grid-template-rows: 100px 100px 100px 100px;
    }

image.png

简单写法 repeat

现在我们如果一行/列有三个项目就需要写3次像素值。那么,如果有十个那就需要写十次,所以为了方便。repeat出现了,见词知意,repeat的意思是重复。

那么刚才我们的写法就可以写成: repeat(3,100px),接收两个参数,第一个是重复次数,第二个是像素值。

 .main {
        width: 600px;
        height: 600px;
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: repeat(3,100px);
        grid-template-rows: 100px 100px 100px 100px;
    }

auto-fill

有时候,单元格的大小是固定的,但是容器的大小是不确定的,比如自适应。这个时候,auto-fill属性就会自动填充。

举个例子

就如腾讯视频的这种卡片(卡片就是单元格并且是固定大小的),当我们缩小屏幕后,容器的宽度改变了,其一行有多少单元格,就会自动分配。

image.png

image.png

我们来使用一下auto-fill

去掉容器的宽高,添加auto-fill后,可以看到如下图,会根据浏览器窗口的变化而改变布局。

 .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: repeat(auto-fill,100px);
        grid-template-rows: 100px 100px 100px 100px;
    }

屏幕录制2022-06-11 下午5.17.48.gif

fr 为了自适应

为了方便比例关系,网格布局提供了fr关键字(fraction的缩写,意为“片段”)。类似于flex布局的 flex:1

如下,我们将容器的一行进行三等分,如下的grid-template-columns: repeat(3,1fr)也就相当于grid-template-columns:1fr 1fr 1fr

 .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: repeat(3,1fr);
        grid-template-rows: 100px 100px 100px 100px;
    }

如图,可以看到是根据窗口宽度,等分的。 image.png 我们缩小一下窗口,又进行了新的宽度分配。 image.png

再看一下,我们按 1:2:3的比例分配。

 grid-template-columns: 1fr 2fr 3fr;

image.png

minmax 最小/大值

minmax() 第一个参数是最小值,第二个参数是最大值。

如下最小值为150px 最大值为1fr,当我们缩小浏览器窗口,可以看到第一列的元素还在变小,而第二列的元素固定在了150px。

 .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: 1fr minmax(150px,1fr);
        grid-template-rows: 100px 100px 100px 100px;
    }

image.png

auto

当我们有三列,我们的第一列和第三列是固定的宽度,然后第二列是自适应的宽度,此时我们就可以使用auto

 .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: 100px auto 100px;
        grid-template-rows: 100px 100px 100px 100px;
    }

image.png

网格线

可以使用方括号定义网格线名称,方便以后的引用。

如下图,横纵方向都有四行/列,然后就有5条网格线。 image.png

针对我们的例子,添加一下。网格线是帮助定位使用的,我们添加后也体现不出效果,我们后面会说到。

    .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: [c1] 100px [c2] 100px [c3] 100px;
        grid-template-rows: 100px 100px 100px 100px;
    }

grid-gap

下面的三个是之前的属性,已经被废弃了。虽然添加后依旧能实现效果,但是不建议使用。

grid-row-gap
grid-column-gap
/* 上面的两个写在了一起 */
grid-gap

新的属性

row-gap
column-gap
/* 上面的两个写在了一起 */
gap
 .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: [c1] 100px [c2] 100px [c3] 100px;
        grid-template-rows: 100px 100px 100px 100px;
        row-gap: 20px;
        column-gap:30px;
    }

image.png

grid-template-areas(*)

一个区域由单个或多个单元格,由你决定。我觉得有点像矩阵(不知道可以这样说吗)。

 grid-template-areas: 'a b c' 
                      'd e f' 
                      'xiao hong xie';
grid-template-areas:  'a a a' 
                      'b b b' 
                      'c c c';

如果 区域不需要利用,可以使用.表示

grid-template-areas:  'a . h' 
                      'b . f' 
                      'c . g';

并且,区域的命名会影响到网格线,每个区域的起始网格线会自动命名为-start,终止网格线自动命名为区域名-end。

grid-auto-flow

划分网格后,容器的子元素会按照顺序,自动的放置在每一个网格,默认的是 先填满第一行,然后再开始第二行。也就是说我们 grid-auto-flow属性,默认是row。

我们将其属性值改为column

    .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: [c1] 100px [c2] 100px [c3] 100px;
        grid-template-rows: 100px 100px 100px 100px;
        gap: 20px 30px;
        grid-template-areas: 'a b c' 'd e f' 'xiao hong xie';
        grid-auto-flow: column;
    }

image.png

还有一个值 dense,它是结合row或者column使用的。

他的作用: 如下图,1和2都很宽,一行是放不下他们两个的。但是为了更好的使用空间,我们可以让3和1在一行。这就是dense的作用。

image.png

我们这里给item1和item2添加了一个grid-column属性,这里可以先不用管。我们后面会提到这个属性。

    .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: [c1] 100px [c2] 100px [c3] 100px;
        grid-template-rows: 100px 100px 100px 100px;
        gap: 20px 30px;
        grid-template-areas: 'a b c' 'd e f' 'xiao hong xie';
        grid-auto-flow: row dense;
    }
   .item1 {
        background-color: rgb(164, 233, 231);
        grid-column: 1/3;
    }

    .item2 {
        background-color: rgb(117, 219, 153);
        grid-column: 1/3;
    }

对齐方式 *-items

注意这里是容器属性的对其方式,在项目(item)中也会有对齐方式。

  • justify-items: 横向对齐
  • align-items: 竖向对齐
  • place-items: justify-items和align-items的组合

我们为其添加值:center

   .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: [c1] 100px [c2] 100px [c3] 100px;
        grid-template-rows: 100px 100px 100px 100px;
        gap: 20px 30px;
        grid-template-areas: 'a b c' 'd e f' 'xiao hong xie';
        justify-items: center;
    }

如图,我们发现变窄了,因为我们并没有给每个子元素添加宽高。然后就按照内容的(字)的宽度进行填充了,只是项目的对齐。

image.png

如下图,网格的宽度还是我们给定的100px,只是其内部的内容变小了。

image.png

对齐方式有哪些

justify-items:stretch

这是默认值,

  • justify-items:stretch也就是让元素横向填满单元格
  • align-items:stretch也就是让元素纵向填满单元格 justify-items:start

可以看出是按照单元格的其实位置开始对齐。 image.png justify-items:center

就是我们上面的例子,居中对齐。

justify-items:end

以单元格的结尾位置进行对齐。

image.png

对齐方式 *-content

内容(content),就是容器(container)中的项目打包在一起(一坨东西)。可以去看我们刚开始的图。

  • justify-content
  • align-content

这一坨,默认的是左对齐

image.png

如下是我把justify-content设为center。这一坨中对齐了 image.png

start | end | center | stretch

justify-content:space-between

两端对齐,留白各列之间均分。 image.png

justify-content:space-around

两端保留子元素与子元素间距的一半。还有留白,列之间等分。

image.png

gird-auto-rows

比如,我只设置了3x3个项目,但是实际有10个项目,这个属性就是用来设置多出来的项目。

  .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: [c1] 100px [c2] 100px [c3] 100px;
        grid-template-rows: 100px 100px 100px;
        gap: 20px 30px;
    }

因为我们并没有对10进行grid-template-rows的设置,它被浏览器自动分配了。 image.png

我们添加 grid-auto-rows属性,后面出现的单元格会自动分配为50px

 grid-auto-rows: 50px;

image.png

项目属性

这里我们涉及到的属性,都是添加到项目上的。

指定item的具体位置

grid-column-start/end

我们让item1以第一个网格线开始,到第三个网格线结束(注意这里是网格线)。

   .item1 {
        background-color: rgb(164, 233, 231);
        grid-column-start: 1;
        grid-column-end:3;
    }

image.png

除了这种使用网格线的方式还有另一种写法:

这里只需要 写 grid-column-start即可。span 3 说明跨了三个单元格。

    .item1 {
        background-color: rgb(164, 233, 231);
        grid-column-start:span 3;
        /* 效果和start一样 */
        /* grid-column-end:span 3;*/
    }

image.png 当然这两个属性也有简写方式grid-column,这里的 / 可不是除号

grid-column: 1/3

gird-rows-start/end

这里和上面同理

grid-area

指定项目放在哪个区域,与我们上面的 grid-template-areas关联。

我们在main中grid-template-areas属性值为grid-template-areas: 'a a a' 'b b b' 'c c c';

 .main {
        display: grid;
        border: 10px solid skyblue;
        grid-template-columns: [c1] 100px [c2] 100px [c3] 100px;
        grid-template-rows: 100px 100px 100px 100px; 
        gap: 20px 30px;
        grid-template-areas: 'a a a' 'b b b' 'c c c';
    }

然后在item1中添加grid-area属性,让其与b区域对应

    .item1 {
        background-color: rgb(164, 233, 231);
        grid-area: b;
    }

如图,item1占据了b区域(三个单元格)的位置。 image.png

作为简写

grid-area 可以替代如下四个属性

  grid-column-start
  grid-column-end
  grid-row-start
  grid-row-end

四个值分别对应:grid-column-start、 grid-row-start、grid-column-end、grid-row-end

grid-area: 1/1/3/3

*-self 对齐

  • justify-self:设置单元格内容水平方向,跟justify-items用法完全一致。
  • align-self:垂直方向
  • place-self: 上面两个的结合

这三个属性和容器中的完全一致,区别在于容器中是针对容器内所有项目的,这三个属性只针对自己项目的对齐。

我们给item1添加 justify-self: center;属性

 .item1 {
        background-color: rgb(164, 233, 231);
        justify-self: center;
     }

可以看到只有item1居中对齐了。 image.png