今天看啥  ›  专栏  ›  samul

日常前端知识——响应式布局之强大的css布局 display:grid

samul  · 掘金  ·  · 2020-05-09 10:27
阅读 133

日常前端知识——响应式布局之强大的css布局 display:grid

1.概览


css display中有个属性值是grid,说起来惭愧的是,在长达近2年的开发实操中我极少用到这个属性。在整理响应式布局的我才重新将其拾起。

grid可以说是在我看来css最强大的布局方案之一了,总体而言,他将网页划分为一个个区域,并且可以对这个区域进行任意组合,以达到布局的效果。(之前这些功能都是一些css框架封装好的,现在css也支持了)

grid和flex有一定的相似性(我在之前的开发过程中flex的应用率极高。。),但flex更像是一种线性的布局,根据横轴和纵轴的各种配置来达到布局的效果。而grid则是一种二维布局,他利用row(行)和column(列)来分割出不同的二维区域,通过对这些二维区域中的一切(是的,几乎是能想到的一切)进行操作来实现不同的布局。

flex布局

flex布局

grid

grid布局

从两张图中可以看出,grid更适用于一些多行多列,宽高不等的复杂布局,从布局的功能上来说,grid远比flex强大的多。

2.基本概念

归纳一下grid的布局一些基本概念,一方面是自身对知识进行梳理,一方面也方便文档的通读性。

2.1 容器(Container)

这也是css布局的传 统 艺 能了,简单的描述来说他就是应用display:grid的元素,同时他也应该是所有项目(item)的直接父元素。

html代码:

<div class="container">
    <div class="item1"></div>
    <div class="item2"></div>
    <div class="item3"><p>No<p></div>
</div>
复制代码

css代码:

.container{
    display:grid
}
复制代码

这里的最外层的div就是整个grid布局的容器

2.2 项目(item)

项目同学们也应该同样熟悉,沿用2.1中的代码,例如item1,item2,item3都是容器(container)的直接子元素,所以他们都是从属于container的项目(item)。

但是要注意的被包裹在item3的<p>No</p>并不是项目(item),他并不是容器(container)的直接子元素

2.3 线(Line)

从线开始往下的概念我会用图片的方式来直观的展示,而如何实现我相信看完属性的详解之后你就自然能够了然于胸了

线

线

图中交错的线就是line(包括了最外层的虚线),所以若是一个容器(container)有4列(column),意味着他有5条列方向的线(line)

2.4 路径(Track)

路径是指相邻两条线(line)包裹的区域

路径
如图中的蓝色track部分就是由col4线(line)和col5线(line)分割出来的路径(track)

2.5 单元格(Cell)

单元格(cell)指分别由两条相邻的行线和两条相邻的列线分割出来的区域(area)

单元格
如图中的cell单元格就是由col3,col4,row2,row3分割出来的一个区域(area),只不过这个区域(area)比较特殊,他是一个单元格(cell)

2.6 区域(Area)

区域(area)是指由两条任意不同的行线和两条任意不同列线分割的区域,它是由若干个单元格(cell)组成的

区域
如图中的红色main区域就是一个由col1,col3和row2,row4分割的区域(area)

2.7 fr

fr单元允许你用等分网格容器剩余可用空间来设置 网格轨道(Grid Track) 的大小。

剩余可用空间是除去所有非灵活网格项之后计算得到的。
复制代码

在这个例子中,可用空间总量减去 100px 后,再给 fr 单元的值 按1:2:1 等分:

   grid-template-columns: [row-one] 1fr [row-two] 2fr [row-three]1fr [row-four] 100px [row-five] ;
复制代码

3.属性


3.1 容器(container)属性

  • display
  • grid-template-columns
  • grid-template-rows
  • grid-template-areas
  • grid-template
  • grid-column-gap
  • grid-row-gap
  • grid-gap
  • justify-items
  • align-items
  • place-items
  • justify-content
  • align-content
  • place-content
  • grid-auto-columns
  • grid-auto-rows
  • grid-auto-flow
  • grid

display


取值: display: grid | inline-grid

grid就不加赘述了,inline-grid的其实就是把这个容器元素变成一个内联元素

grid-template-columns / grid-template-rows


取值:

  • <track-size>: 可以是长度值,百分比,或者等份网格容器中可用空间(使用 fr 单位)
  • <line-name>:给你的线(line)任意的起个名字

html代码:

    <body>
        <div class="container">
            <div class="item1 center"></div>
            <div class="item2 center"></div>
            <div class="item3 center"></div>
            <div class="item4 center"></div>
            <div class="item5 center"></div>
        </div>
    </body>
复制代码

css代码:

.container {
    display: grid;
    grid-template-columns: [row-one] 100px [row-two] 100px [row-three]100px [row-four] 100px [row-five] ;
    grid-template-rows: 100px 100px auto 100px;
  }

.center{
    display: flex;
    justify-content: center;
    align-items: center;
}
复制代码

3.1

你可以明确指定网格线的名称,就像代码中对grid-template-columns中所做一样。 你也会发现容器中对项目的排序默认是按行进行,从左往右,从上往下。如图中所示的那样,但这就出现了一个问题,本该在第二行第一个的item5去哪了呢?

答案就是grid-template-rows: 100px 100px auto 100px;中这个auto的锅了,属性值为auto的情况下,它会默认设置为子元素所需的高度,但是item5中并没有子元素,于是row2就“消失”了。

尝试着给item5添加一个text

...
<div class="item5 center">text</div>
...

复制代码

3.2

如图,item5在row2中出现了

grid-template-areas


grid-area属性可以指定一个网格区域(Grid Area) 名称来定义网格模板。

重复网格区域的名称导致内容跨越这些单元格。一个点号(.)代表一个空单元格。这个语法本身可视作网格的可视化结构。

值:

  • <grid-area-name>:由网格项的 grid-area 指定的网格区域名称
  • .(点号) :代表一个空的网格单元
  • none:不定义网格区域

直接上代码:

3.3

grid-template-areas: 
  "none header header sidebar"
  "main main simpleCell sidebar"
  "main main footer .";
  .item1 {
    grid-area: header;
    background-color: orange;
  }
  .item2 {
    grid-area: main;  
    background-color: red;
  }
  .item3 {
    grid-area: sidebar;
    background-color: blue;
    color: white;
    font-size: 30px;
  }
  .item4 {
    grid-area: footer;
    background: green;
  }
  .item5 {
    grid-area: simpleCell;
    background: #694545;
  }
复制代码

通俗一点。grid-template-areas中写一个命名方阵,然后item(项目)中用grid-area属性使用其中的命名来进行对应。

tips:在grid-template-areas中的命名分布必须是一个矩形

grid-column-gap/grid-row-gap


指定网格线(line)的大小。相当于设置行和列的间距

话不多说上代码

grid-column-gap:50px;
grid-row-gap:25px;
复制代码

3.4

行列的距离被分开了!需要注意的是如果你的区域(area)包含多个单元格(cell),区域的width将会把线(line)的宽度计算在内!

justify-items


justify-items可以在行轴上设置item们在各自area中的对齐方式

可取的值:

  • start:将网格项对齐到其单元格的左侧起始边缘(左侧对齐)
  • end:将网格项对齐到其单元格的右侧结束边缘(右侧对齐)
  • center:将网格项对齐到其单元格的水平中间位置(水平居中对齐)
  • stretch:填满单元格的宽度(默认值)

直接上代码体验一下:

justify-items: start;
复制代码

3.5

justify-items: center;
复制代码

3.6

justify-items: end;
复制代码

3.7

需要注意的点是,header,main和siderbar其实是占据的是一个由多个cell组成的area,所以他的位置会取area的起始,中间,和尾部

align-items


justify-items可以在列轴上设置item们在各自area中的对齐方式

可取的值:

  • start:将网格项对齐到其单元格的顶部起始边缘(顶部对齐)
  • end:将网格项对齐到其单元格的底部结束边缘(底部对齐)
  • center:将网格项对齐到其单元格的垂直中间位置(垂直居中对齐)
  • stretch:填满单元格的高度(默认值)

这个的实际效果可以参考justify-items,可以自行尝试。

place-items


place-items是align-items和justify-items的合并写法

可取的值:

  • <align-items> <justify-items>

第一个值设置给align-items,第二个值设置给justify-items,如果只设置第一个值那么这个值将同时赋予 align-items和justify-items

justify-content

有时候,你的item们加起来的宽度都没有container的大,同时item们使用的都是px等固定宽度的长度单位,那么这时候就可能需要justify-content出马来调整item们来到达你想要的位置了。

可取的值:

  • start:将网格对齐到 网格容器(grid container) 的左侧起始边缘(左侧对齐)
  • end:将网格对齐到 网格容器 的右侧结束边缘(右侧对齐)
  • center:将网格对齐到 网格容器 的水平中间位置(水平居中对齐)
  • stretch:调整 网格项(grid items) 的宽度,允许该网格填充满整个 网格容器 的宽度
  • space-around:在每个网格项之间放置一个均匀的空间,左右两端放置一半的空间
  • space-between:在每个网格项之间放置一个均匀的空间,左右两端没有空间
  • space-evenly:在每个网格项目之间放置一个均匀的空间,左右两端放置一个均匀的空间

依次放图:

3.8

justify-content: start

3.9

justify-content: center

3.10

justify-content: end

3.11

justify-content: space-around;

3.12

justify-content: space-between;

3.13

justify-content: space-evenly;

align-content


justify-content的列轴版。赋值什么的都一模一样的,建议自己尝试一哈

place-content


place-content是align-content和justify-content的合并写法

可取的值:

  • <align-content> <justify-content>

第一个值设置给align-content,第二个值设置给justify-content,如果只设置第一个值那么这个值将同时赋予 align-content和justify-content

grid-auto-columns / grid-auto-rows


指定自动生成的track的高度/宽度,当container中item多于cell的数量,或者item的定位在当前所有的cell之外时候,container就会自动创建(隐式轨道),来以此填补缺少的位置。

可取的值:

  • <track-size>:可以是长度值,百分比,或者等份网格容器中可用空间的分数(使用 fr 单位)

上代码:

.container {
    width: 100%;
    display: grid;
    grid-template-columns: 100px 100px 100px 100px ;
    grid-template-rows: 100px 100px 100px 100px;
    grid-auto-columns:70px;
    grid-auto-rows: 70px;
    border: 1px solid black;
    grid-template-areas: 
      "none header header sidebar"
      "main main simpleCell sidebar"
      "main main footer .";
}

    ...

  .item6 {
    width: 100%;
    grid-column: 6;
    grid-row: 5;
    background: #694545;
  }
复制代码

3.14

可以看到,这个container初始是由一个4*4的row和column组成的,但是在item6中使用了grid-column/grid-row将其指定在5行6列的位置,那么此刻,container就会创建隐式轨道(图中的虚线部分)。grid-auto-columns和grid-auto-rows就是分别用来指定隐式轨道的列宽和行高。

grid-auto-flow


如果你有一些item,并且他们没有被指定放置的位置,那么这个时候container会按照一定规则去排列他们,grid-auto-flow可以设置这个规则。

可取的值:

  • row:依次填充每行,根据需要添加新行 (默认)
  • column:依次填入每列,根据需要添加新列
  • dense:在稍后出现较小的网格项时,尝试填充网格中较早的空缺

上代码:

通用部分——

      .item1 {
        width: 100%;
        grid-column: 1 / span 3;
        // grid-area: header;
        background-color: orange;
      }
      .item2 {
        // grid-area: main; 
        width: 100%;
        grid-column: 1 / span 2; 
        background-color: red;
      }
      .item3 {
        width: 110px;
        // grid-area: sidebar;
        background-color: blue;
        color: white;
        font-size: 30px;
      }
      .item4 {
        width: 100px;
        // grid-area: footer;
        background: green;
      }
      .item5 {
        width: 100px;
        // grid-area: simpleCell;
        background: #694545;
      }
      .item6 {
        width: 100%;
        background: #694545;
      }
复制代码

grid-auto-flow: row;

3.15

grid-auto-flow: column;

3.16

grid-auto-flow: row dense;

3.17

grid-auto-flow: column dense;

  .item1 {
    width: 100%;
    grid-row: 1 / span 3;
    // grid-area: header;
    background-color: orange;
  }
  .item2 {
    // grid-area: main; 
    width: 100%;
    grid-row: 1 / span 2; 
    background-color: red;
  }
复制代码

3.18

项目(item)属性


Tips: float,display: inline-block,display: table-cell,vertical-align 和 column-* 属性对item无效

grid-column-start / grid-column-end / grid-row-start / grid-row-end与 grid-column / grid-row

通过引用特定线(lines) 来确定item在网格内的位置。

grid-column-start / grid-row-start 是网格项开始的网格线。

grid-column-end / grid-row-end 是网格项结束的网格线。

在使用时要注意的是 如果使用了以上这些子属性来进行布局,请不要同时使用grid-area来配合container中的grid-template-areas。前者会被后者的布局效果所覆盖

上代码

.container {
    grid-template-columns: [col-1]100px [col-2] 100px [col-3]100px [col-4] 100px [col-5];
    grid-template-rows: [row-1]100px [row-2]100px [row-3]100px [row-4]100px[row-5];
    grid-auto-columns:70px;
    grid-auto-rows: 70px;
  ...
    .item1 {
      grid-column-start: 1;
      grid-column-end: span col-4;
      grid-row-start: 2;
      grid-row-end: span 2;
      width: 100%;
      // grid-area: header;
      background-color: orange;
      z-index: 100;
    }
}
复制代码

3.19
以上代码中我们对每一条line进行了命名,以方便我们进行布局

item1 即是 图中的heaher部分。可以看到,从列来说,他从1也就是最左侧的col-1开始,一直到col4结束。从行来说,他从由上至下的2也就是row-2开始,跨域了2条线。

span X代表着从该线开始的第X根线结束,你也可以用线的名称直接来指定位置,比如row-1,col-2,前提是你得命名。

grid-column / grid-row是上述4个属性的简写方法。

上述属性同样可以写成

grid-column: 1 / span col-4;
grid-row: 2 / span 2;
复制代码

grid-area


可取的值:

  • <name>:在container中指定的名称
  • <row-start> / <column-start> / <row-end> / <column-end>:数字或线名称

其实前面一直在用...已经非常眼熟了。并不推荐<row-start> / <column-start> / <row-end> / <column-end>的写法,可读性很差。远不如指定<name>

justify-self


container属性justify-items的item单项目版,取值和效果完全一致

align-self


container属性align-items的item单项目版,取值和效果完全一致

place-self


justify-selfalign-self 的合并简写

可取的值:

  • auto 默认
  • <align-self> <justify-self>,如果只写一个,它同时将被赋值给第二个



原文地址:访问原文地址
快照地址: 访问文章快照