重新认识grid布局

1,943 阅读10分钟

grid基本没有使用过,做项目一般使用的都是flex布局。前两天在牛客上看见一个关于grid的面试题。所以现在来复习一个grid布局。

什么是grid布局

Flex 布局是轴线布局,只能指定“项目”针对轴线的位置,可以看作是一维布局。

Grid 布局则是将容器划分 成“行”和“列”,产生单元格,然后指定“项目所在”的单元格,可以看作是二维布局,Grid 布局远比 Flex 布 局强大。 因为他可以把每个盒子任意排放到理想的位置。

但是兼容性和flex相比就差一些了。可以通过can i use查看兼容性

核心内容

image.png

  • 容器属性 image.png
  • 项目属性 image.png

容器属性

grid-template-columns

你想要多少列,就填写相应元素占的列宽,不填写,自动分配,占满整个容器。

    grid-template-colums: 100px 100px 100px;
  • repeat(num, width)来指定个数和宽度。
    grid-template-colums: repeat(3, 100px);

其中repeat第一个参数值还可以是auto-fill,表示容器没有设置宽高时,然后元素宽高固定,然后容器自动撑开,直到一行的空间不能剩下一个元素为止,然后换行展示。

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

grid02.gif

  • fr单位 每个定义了 flex 的网格轨道会按比例分配剩余的可用空间。会按照指定的每份进行对父容器的分配。
    grid-template-columns: 1fr 2fr 3fr;

image.png

  • 百分比单位 他是根据容器宽度和高度分配的。
  grid-template-rows: 10% 30% 50%;
  grid-template-columns: 10% 30% 50%;

image.png

  • minmax()属性 是一个来定义大小范围的属性,大于等于min值,并且小于等于max值。如果max值小于min值,则该值会被视为min值最大值可以设置为网格轨道系数值<flex>即fr单位,但最小值则不行。
   grid-template-columns: 1fr minmax(500px, 2fr);

grid03.gif

  • min-content属性 是一个用来表示以网格项的最大的内容来占据网格轨道的关键字。
  • max-content属性 是一个用来表示以网格项的最大的最小内容来占据网格轨道的关键字。
  • auto属性。 让列宽自动分配宽度。如果该网格轨道为最大时,该属性等同于 <max-content> ,为最小时,则等同于 <min-content> 。
  • 网格线。 可以用方括号定义网格线名称,方便以后的引用。
  grid-template-columns: [a1] 1fr [a2] 2fr [a3] 3fr [a4];

grid-template-rows

你想要多少行,就填写相应元素占的行高,不填写,自动分配,占满整个容器。

他的属性值和grid-template-colums一样的,下面来介绍一下注意事项。

如果同时指定grid-template-colums, grid-template-rows,元素不够展示行和列,那么默认列的优先级高于行。 skicy02.gif 如果定义的项的宽之和、高度值和大于容器定义的宽高,那么将超出容器。

  width: 800px;
  height: 400px;
  grid-template-columns: 200px 300px 400px;

image.png

row-gap,即以前的grid-row-gap

设置行元素之间的间隙gutter 大小。

  grid-template-rows: 100px 100px 100px 100px;
  grid-template-columns: 10% 30% 50%;
  row-gap: 10px;

image.png 从上面可以看出,如果间距加上元素高度大于容器高度,那么将会超出容器。所以一般用等比分陪的单位,即fr单位。因为他分配的是剩余的可用空间。

  grid-template-rows: 1fr 2fr 3fr;
  grid-template-columns: 10% 30% 50%;
  row-gap: 10px;

image.png 如果设置百分比单位时,他是依据容器的高度计算的。

column-gap,即以前的grid-colum-gap

设置列元素之间的间隙gutter 大小。

  grid-template-rows: 100px 100px 100px 100px;
  grid-template-columns: 10% 30% 50%;
  column-gap: 70px;

image.png 设置间距,只会设置两个元素之间的,两边的元素不会设置。

如果设置百分比单位时,他是依据容器的宽度计算的。

gap,即以前的grid-gap

用来设置网格行与列之间的间隙gutters,该属性是row-gapand column-gap的简写形式。

  width: 800px;
  height: 400px;
  grid-template-rows: 1fr 2fr 3fr;
  grid-template-columns: 10% 30% 50%;
  gap: 10%;

image.png

grid-template-areas

一个区域由单个或多个单元格组成。

每一个给定的字符串会生成一行,一个字符串中用空格分隔的每一个单元(cell)会生成一列。 多个同名的,跨越相邻行或列的单元称为网格区块(grid area)。非矩形的网格区块是无效的。

    grid-template-areas: "a a a" "b c c" "b c c";

这个属性可以参考mdn, 便于理解。

区域不需要利用,则使用.表示区域的命名会影响到网格线。每个区域的起始网格线, 会自动命名为区域名-start,终止网格线自动命名为区 域名-end。

    grid-template-areas: "a a ." "a a ." ". b c";

grid-auto-flow

元素的排列方式,默认情况下,元素是按照行依次排列的。精确指定在网格中被自动布局的元素怎样排列。

  // grid-auto-flow: row; // 默认情况。横向依次排列。
  grid-auto-flow: column;

image.png 划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是“先行后列”, 即先填满第一行,再开始放入第二行 (就是子元素的排放顺序)。 image.png 它还可以设置一个特殊的值。dense

  • 该关键字指定自动布局算法使用一种“稠密”堆积算法,如果后面出现了稍小的元素,则会试图去填充网格中前面留下的空白。 这样做会填上稍大元素留下的空白,但同时也可能导致原来出现的次序被打乱。
   .container {
      display: grid;
      width: 800px;
      height: 400px;
      border: 5px solid orange;
      grid-template-rows: 1fr 2fr 3fr;
      grid-template-columns: 100px 100px 100px;
      grid-auto-flow: dense;
      /* grid-auto-flow: row; */
      /* grid-auto-flow: column; */
    }

    .item1 {
      background: red;
      grid-column: 1 / 3;
    }

    .item2 {
      background: rgb(238, 235, 34);
      grid-column: 1 / 3;
    }

grid04.gif 这个属性也可以指定两个属性值,第一个是column / row, 第二个值只能是dense。

  grid-auto-flow: row dense;

justify-items

设置单元格内容的水平对齐方式。

  justify-items: start;

image.png 该属性的值,请查看mdn

align-items

设置单元格内容的垂直对齐方式。

    justify-items: start;
    align-items: center;

image.png

place-items

他是align-items和justify-items的简写方式。

  /* 先垂直,后水平 */
  place-items: center start;

image.png

justify-content

表示全部单元格相对容器的横向对齐方式。

  justify-content: center;

image.png

align-content

表示全部单元格相对容器的纵向对齐方式。

  grid-template-rows: 100px 100px 100px;
  grid-template-columns: 100px 100px 100px;
  justify-content: center;
  align-content: center;

image.png 从上面可以看出,如果我们未指定单元格的宽度和高度,那么它将会被压缩,由内容撑开。

  grid-template-rows: 100px 100px 100px 100px; // +
  grid-template-columns: 100px 100px 100px;
  justify-content: center;
  align-content: center;

image.png

place-content

他是align-content和justify-content的简写方式。

  place-content: start center;

image.png

grid-auto-columns

设置多出来的元素单元格的列宽。

  display: grid;
  width: 800px;
  height: 400px;
  border: 5px solid orange;
  grid-template-rows: 100px 100px 100px;
  grid-template-columns: 100px 100px 100px;
  grid-auto-columns: 60px;
  grid-auto-rows: 60px;

我们设置了10个元素,但是我们只设置了三行三列,所以会多出一个单元格。那么这个属性就会和列等宽,并且不能修改。 image.png 但是我们可以通过设置单元格的排列顺序,即grid-auto-flow属性,来让grid-auto-columns生效。

  display: grid;
  width: 800px;
  height: 400px;
  border: 5px solid orange;
  grid-template-rows: 100px 100px 100px;
  grid-template-columns: 100px 100px 100px;
  grid-auto-columns: 60px;
  grid-auto-rows: 60px;
  grid-auto-flow: column;

image.png

grid-auto-rows

设置多出来的元素单元格的行高。

  display: grid;
  width: 800px;
  height: 500px;
  border: 5px solid orange;
  grid-template-rows: 100px 100px 100px;
  grid-template-columns: 100px 100px 100px;
  grid-auto-columns: 60px;
  grid-auto-rows: 60px;

我们设置了10个元素,但是我们只设置了三行三列,所以会多出一个单元格。默认情况,他会占满剩余空间。但是我们可以设置该属性来指定该元素的高度。 image.png

项目属性

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

  • 直接指定数字(正数) 表示设置单元格的宽度和高度。从第几个网格线开始,到底几个网格线结束。
   .container {
      display: grid;
      width: 800px;
      height: 400px;
      border: 5px solid orange;
      grid-template-rows: 100px 100px 100px;
      grid-template-columns: 100px 100px 100px;
    }

    .item1 {
      background: red;
      grid-column-start: 1;
      grid-column-end: 6;
      grid-row-start: 1;
      grid-row-end: 4;
    }

image.png 从上面可以看出,这里就不会去满足容器中指定的几行几列了。

  • 指定负数。表示从右往左开始。
   .item1 {
      background: red;
      /* grid-column-start: 1;
      grid-column-end: 6; */
      grid-column-start: -1;
      grid-column-end: -3;
      grid-row-start: 1;
      grid-row-end: 4;
    }

image.png

  • 该属性值也可以设置容器中定义grid-template-columns, grid-template-rows中定义的网格线名字。
.container {
  display: grid;
  width: 800px;
  height: 400px;
  border: 5px solid orange;
  grid-template-rows: [r1] 100px [r2] 100px [r3] 100px [r4];
  grid-template-columns: [a1] 100px [a2] 100px [a3] 100px [a4];
}

.item1 {
  background: red;
  grid-column-start: a1;
  grid-column-end: a3;
  grid-row-start: r1;
  grid-row-end: r4;
}

image.png

  • 该属性的第一个值可以指定为span, 然后加上一个数字或者容器中定义grid-template-columns, grid-template-rows中定义的网格线名字。 表示跨域几个单元格,或者跨越到那个网格线。 grid-column-start表示从左向右,grid-column-end表示从右向左。grid-row-start表示从上到下,grid-row-end表示从下到上。
.container {
  display: grid;
  width: 800px;
  height: 400px;
  border: 5px solid orange;
  grid-template-rows: [r1] 100px [r2] 100px [r3] 100px [r4];
  grid-template-columns: [a1] 100px [a2] 100px [a3] 100px [a4];
}

.item1 {
  background: red;

  grid-column-start: span 3;
  grid-row-start: span r2;
}

image.png

grid-column、grid-row

分别为grid-column-start、grid-column-end 和 grid-row-start、grid-row-end的简写。

  grid-column: 2 / 4;
  grid-row: 2 / 4;

image.png

grid-area

指定该项放在那个区域。这个区域的定义是在容器的grid-template-areas

   .container {
      display: grid;
      width: 800px;
      height: 400px;
      border: 5px solid orange;
      grid-template-rows: [r1] 100px [r2] 100px [r3] 100px [r4];
      grid-template-columns: [a1] 100px [a2] 100px [a3] 100px [a4];

      grid-template-areas:
        "a a a"
        "b c c"
        "b c c";
    }

    .item1 {
      background: red;
      grid-area: c;
    }

image.png 这个属性可以很好地控制元素的位置。

  • grid-area属性还可用作grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并 简写形式,直接指定项目的位置。
  grid-area: r2 / a3 / 4 / 4;

image.png

justify-self

定义指定单元格的内容水平方向排列顺序。默认值为stretch。表示占满整个单元格宽度。

  justify-self: center;

image.png

align-self

定义指定单元格的内容垂直方向排列顺序。默认值为stretch。表示占满整个单元格高度。

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

image.png

place-self

align-self和justify-self属性的简写形式。

  place-self: center start;

image.png

具体的值请访问mdn吧。其实这些单元格或者全部单元格的排列方式和flex布局一样。想要了解他的形式,请访问mdn。

练习

grid制作骰子

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #box1 {
      width: 100px;
      height: 100px;
      border-radius: 10%;
      border: 1px solid black;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      justify-items: center;
      align-items: center;
    }

    #box1 div {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 2/2/3/3;
    }


    /* #box2{width:100px;height:100px;border-radius: 10%;border:1px solid black;display: grid;grid-template-columns: repeat(4,1fr);
        grid-template-rows: repeat(4,1fr);justify-items: center;align-items: center;
        }
        #box2 div:nth-child(1){width:20px;height:20px;background:black;border-radius: 50%;;grid-area: 2/2/3/3;}
        #box2 div:nth-child(2){width:20px;height:20px;background:black;border-radius: 50%;;grid-area: 3/3/4/4;} */



    #box2 {
      width: 100px;
      height: 100px;
      border-radius: 10%;
      border: 1px solid black;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      justify-items: center;
      align-items: center;
    }

    #box2 div:nth-child(1) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/1/2/2;
    }

    #box2 div:nth-child(2) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/3/4/4;
    }



    #box3 {
      width: 100px;
      height: 100px;
      border-radius: 10%;
      border: 1px solid black;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      justify-items: center;
      align-items: center;
    }

    #box3 div:nth-child(1) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/1/2/2;
    }

    #box3 div:nth-child(2) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 2/2/3/3;
    }

    #box3 div:nth-child(3) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/3/4/4;
    }


    /* #box4{width:100px;height:100px;border-radius: 10%;border:1px solid black;display: grid;grid-template-columns: repeat(4,1fr);
        grid-template-rows: repeat(4,1fr);justify-items: center;align-items: center;
        }
        #box4 div:nth-child(1){width:20px;height:20px;background:black;border-radius: 50%;;grid-area: 2/2/3/3;}
        #box4 div:nth-child(2){width:20px;height:20px;background:black;border-radius: 50%;;grid-area: 2/3/3/4;}
        #box4 div:nth-child(3){width:20px;height:20px;background:black;border-radius: 50%;;grid-area: 3/2/4/3;}
        #box4 div:nth-child(4){width:20px;height:20px;background:black;border-radius: 50%;;grid-area: 3/3/4/4;} */

    #box4 {
      width: 100px;
      height: 100px;
      border-radius: 10%;
      border: 1px solid black;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      justify-items: center;
      align-items: center;
    }

    #box4 div:nth-child(1) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/1/2/2;
    }

    #box4 div:nth-child(2) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/3/2/4;
    }

    #box4 div:nth-child(3) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/1/4/2;
    }

    #box4 div:nth-child(4) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/3/4/4;
    }


    #box5 {
      width: 100px;
      height: 100px;
      border-radius: 10%;
      border: 1px solid black;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      justify-items: center;
      align-items: center;
    }

    #box5 div:nth-child(1) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/1/2/2;
    }

    #box5 div:nth-child(2) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/3/2/4;
    }

    #box5 div:nth-child(3) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 2/2/3/3;
    }

    #box5 div:nth-child(4) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/1/4/2;
    }

    #box5 div:nth-child(5) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/3/4/4;
    }


    #box6 {
      width: 100px;
      height: 100px;
      border-radius: 10%;
      border: 1px solid black;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      justify-items: center;
      align-items: center;
    }

    #box6 div:nth-child(1) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/1/2/2;
    }

    #box6 div:nth-child(2) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 1/3/2/4;
    }

    #box6 div:nth-child(3) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 2/1/3/2;
    }

    #box6 div:nth-child(4) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 2/3/3/4;
    }

    #box6 div:nth-child(5) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/1/4/2;
    }

    #box6 div:nth-child(6) {
      width: 20px;
      height: 20px;
      background: black;
      border-radius: 50%;
      ;
      grid-area: 3/3/4/4;
    }
  </style>
</head>

<body>
  <div id="box1">
    <div></div>
  </div>

  <div id="box2">
    <div></div>
    <div></div>
  </div>

  <div id="box3">
    <div></div>
    <div></div>
    <div></div>
  </div>

  <div id="box4">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>

  <div id="box5">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>

  <div id="box6">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>
</body>

</html>

image.png

移动布局案例

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    #content {
      width: 321px;
      height: 425px;
      border: 1px black solid;
      margin: 30px auto;
    }

    #parent {
      width: 278px;
      height: 346px;
      color: white;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(4, 1fr);
      grid-template-areas: "a1 a2 a2""a3 a2 a2""a4 a4 a5""a6 a7 a7";
      justify-content: space-evenly;
      grid-gap: 8px 8px;
    }

    #text {
      color: black;
      font-size: 14px;
      margin-top: 7px;
      margin-bottom: 7px;
      margin-left: 15px;
    }

    #parent div:nth-of-type(1) {
      grid-area: a1;
      background: #1f99f5;
      /* width:87px;height:81px; */
      display: grid;
    }

    #parent div:nth-of-type(1) p {
      font-size: 12px;
      justify-self: end;
      margin-top: 3px;
      margin-right: 3px;
    }

    #parent div:nth-of-type(1) h3 {
      font-size: 14px;
      justify-self: center;
      margin-top: -27px;
    }

    #parent div:nth-of-type(2) {
      grid-area: a2;
      background: #1f99f5;
      display: grid;
    }

    #parent div:nth-of-type(2) p {
      font-size: 12px;
      justify-self: end;
      margin-top: 3px;
      margin-right: 3px;
    }

    #parent div:nth-of-type(2) h3 {
      font-size: 14px;
      justify-self: center;
      margin-top: -74px;
    }

    #parent div:nth-of-type(3) {
      grid-area: a3;
      background: #ff4074;
      display: grid;
    }

    #parent div:nth-of-type(3) p {
      font-size: 12px;
      justify-self: end;
      margin-top: 3px;
      margin-right: 3px;
    }

    #parent div:nth-of-type(3) h3 {
      font-size: 14px;
      justify-self: center;
      margin-top: -20px;
    }

    #parent div:nth-of-type(4) {
      grid-area: a4;
      background: #1f99f5;
      display: grid;
    }

    #parent div:nth-of-type(4) p {
      font-size: 12px;
      justify-self: end;
      margin-top: 3px;
      margin-right: 3px;
    }

    #parent div:nth-of-type(4) h3 {
      font-size: 14px;
      justify-self: center;
      margin-top: -19px;
    }

    #parent div:nth-of-type(5) {
      grid-area: a5;
      background: #1f99f5;
      display: grid;
    }

    #parent div:nth-of-type(5) p {
      font-size: 12px;
      justify-self: end;
      margin-top: 3px;
      margin-right: 3px;
    }

    #parent div:nth-of-type(5) h3 {
      font-size: 14px;
      justify-self: center;
      margin-top: -19px;
    }

    #parent div:nth-of-type(6) {
      grid-area: a6;
      background: #e07100;
      display: grid;
    }

    #parent div:nth-of-type(6) p {
      font-size: 12px;
      justify-self: end;
      margin-top: 3px;
      margin-right: 3px;
    }

    #parent div:nth-of-type(6) h3 {
      font-size: 14px;
      justify-self: center;
      margin-top: -19px;
    }

    #parent div:nth-of-type(7) {
      grid-area: a7;
      background: #e07100;
      display: grid;
    }

    #parent div:nth-of-type(7) p {
      font-size: 12px;
      justify-self: end;
      margin-top: 3px;
      margin-right: 3px;
    }

    #parent div:nth-of-type(7) h3 {
      font-size: 14px;
      justify-self: center;
      margin-top: -19px;
    }

    #parent {
      margin: 0 auto;
    }
  </style>
</head>

<body>
  <div id="content">
    <h2 id="text">今日上榜</h2>
    <div id="parent">
      <div>
        <p>七日关注</p>
        <h3>高通技术授权</h3>
      </div>
      <div>
        <p>热门搜索</p>
        <h3>美国中期选举</h3>
      </div>
      <div>
        <p>七日关注</p>
        <h3>双11消费提示</h3>
      </div>
      <div>
        <p>热门搜索</p>
        <h3>迪士尼收购福克斯</h3>
      </div>
      <div>
        <p>体育热点</p>
        <h3>上港首夺中超</h3>
      </div>
      <div>
        <p>体育热点</p>
        <h3>王思聪抽奖</h3>
      </div>
      <div>
        <p>七日关注</p>
        <h3>苹果遭起诉</h3>
      </div>
    </div>
  </div>
</body>

</html>

image.png 兄弟们,咱就说如果你觉得稍微有一点点收获,请来个star吧。谢谢。