阅读 1857

grid 网格布局(grid网格布局兼容性)

引入

  对于Web开发者来说,网页布局一直是个比较重要的问题。但实际上,在网页开发很长的一段时间当中,我们甚至没有一个比较完整的布局模块。总的来说 Web 布局经历了以下四个阶段:

  1、table表格布局,通过 Dreamweaver 拖拽表格或者手写 table 标签布局

  2、float浮动及position定位布局,借助元素元素盒模型本身的特性以及 float position 等属性等进行布局

  3、flex弹性盒模型布局,革命性的突破,解决传统布局方案上的三大痛点 排列方向、对齐方式,自适应尺寸。是目前最为成熟和强大的布局方案

  4、grid栅格布局,二维布局模块,具有强大的内容尺寸和定位能力,适合需要在两个维度上对齐内容的布局

什么是 grid 布局

Grid 布局即网格布局,是一种新的 CSS 布局模型,比较擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。号称是最强大的的 CSS 布局方案,是目前唯一一种 CSS 二维布局。利用 Grid 布局,我们可以轻松实现类似下图布局,演示地址

image.png

Grid 布局和 flex 布局

讲到布局,我们就会想到 flex 布局,甚至有人认为竟然有 flex 布局了,似乎没有必要去了解 Grid 布局。但 flex 布局和 Grid 布局有实质的区别,那就是 flex 布局是一维布局,Grid 布局是二维布局flex 布局一次只能处理一个维度上的元素布局,一行或者一列。Grid 布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到我们布局的目的。

所以Grid更适合页面宏观的架构搭建,flex更擅长局部行列布局。

flex布局示例:

Grid 布局示例:

Grid 布局

Grid 布局兼容性

最后,聊聊 Grid 布局兼容性问题,在 caniuse 中,我们可以看到的结果如下,总体兼容性还不错,但在 IE 10 以下不支持。个人建议在公司的内部系统运用起来是没有问题的,但 TOC 的话,可能目前还是不太合适

image

Grid 的一些基础概念

网格布局是一种二维布局结构,它是由纵横相交的两组网格线形成的框架性布局结构。网页设计者可以利用这些由行(row)和列(column)形成的框架性结构来布局设计元素。 在定义一种网格布局结构的时候,我们需要在父容器上描述要布局的主体框架结构。为了描述这一框架结构,我们就需要给它的基本构成元素命名。一个网格布局的构成元素可以概括为以下几种概念:

  • row line: 行线

  • column line: 列线

  • track: 网格轨道,即行线和行线,或列线和列线之间所形成的区域,用来摆放子元素

  • gap: 网格间距,行线和行线,或列线和列线之间所形成的不可利用的区域,用来分隔元素

  • cell: 网格单元格,由行线和列线所分隔出来的区域,用来摆放子元素

  • area: 网格区域,由单个或多个网格单元格组成,用来摆放子元素!

牢记上述这些概念是之后熟练掌握和应用网格布局的基础。

image.png

容器属性介绍

虽然网格布局好处有很多,但学习起来并不简单,原因是用来设置布局的属性实在太多,其中光是作用于父容器的属性就有17种,再加上子元素属性有10种,另外还有这些属性值的不同取值方式。这些对于记忆来说绝对是个不小的负担。那么这么多属性以及用法,要如何在短时间内消化掉呢?建议可以跟 demo 一起结合起来,边敲代码边理解,再利用一些空闲时间记忆一下。Grid 布局属性可以分为两大类,一类是容器属性,一类是项目属性。我们先来看容器属性

启用网格容器

我们使用display属性来定义一个网格容器,它的grid值决定了容器展现为块级还是内联形式。一旦启用网格容器,它的所有子元素都进入grid文档流,称为网格子项。

display: grid | inline-grid | subgrid复制代码
  • grid:定义一个块级的网格容器

  • inline-grid:定义一个内联的网格容器

  • subgrid:定义一个继承其父级网格容器的行和列的大小的网格容器,它是其父级网格容器的一个子项。

注意:column, float, clear和vertical-align对网格容器没有效果。

.wrapper { 
    display: grid; 
}
.wrapper-1 { 
    display: inline-grid; 
}
.test1, test2{
    display: inline-block; 
}复制代码

image.png

grid-template-columns 属性和 grid-template-rows 属性

词法:

grid-template-columns: <track-size> ... | <line-name> <track-size> ...;

grid-template-rows: <track-size> ... | <line-name> <track-size> ...;复制代码
  • <track-size>:定义网格单元的宽高,其单位可以是一个长度(如px、em、rem、vw、vh)或百分比,也可以是网格中自由空间的份数(单位为fr)。

  • <line-name>:定义网格线的名称,它不是必须值。可以一个你选择的任意名字,当没有显示设定时,它的名字以数字表示。

实例:

当你在轨迹值中间留空格,网格线将被自动以数字命名:

.wrapper{   
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}复制代码

当然,我们还可以给网格线指定一个名字:

.wrapper{   
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];   
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];  
}复制代码

\

注意:网格线命名时必须加上中括号.复制代码

一根网格线还可以有多个名字,以空格隔开,中括号包裹:

.wrapper{   
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];  
}复制代码

repeat() 函数

可以简化重复的值。该函数接受两个参数,第一个参数是重复的次数,第二个参数是所要重复的值。比如上面行高都是一样的,我们可以这么去实现,实际效果是一模一样的;

.wrapper{ 
    /* 2行,而且行高都为 50px */ 
    grid-template-rows: repeat(2, 50px); 
}复制代码

auto-fill 关键字

表示自动填充,让一行(或者一列)中尽可能的容纳更多的单元格。grid-template-columns: repeat(auto-fill, 200px) 表示列宽是 200 px,但列的数量是不固定的,只要浏览器能够容纳得下,就可以放置元素,代码以及效果如下所示:

.wrapper{ 
    grid-template-columns: repeat(auto-fill, 200px);
}复制代码

fr 关键字

Grid 布局还引入了一个另外的长度单位来帮助我们创建灵活的网格轨道。fr 单位代表网格容器中可用空间的一等份。grid-template-columns: 200px 1fr 2fr 表示第一个列宽设置为 200px,后面剩余的宽度分为两部分,宽度分别为剩余宽度的 1/3 和 2/3。代码以及效果如下图所示:

.wrapper{ 
    grid-template-columns: 200px 1fr 2fr;
}复制代码

minmax() 函数

我们有时候想给网格元素一个最小和最大的尺寸,minmax() 函数产生一个长度范围,表示长度就在这个范围之中都可以应用到网格项目中。它接受两个参数,分别为最小值和最大值。grid-template-columns: 1fr 1fr minmax(300px, 2fr) 的意思是,第三个列宽最少也是要 300px,但是最大不能大于第一第二列宽的两倍。代码以及效果如下:

.wrapper{ 
    grid-template-columns: 1fr 1fr minmax(300px, 2fr);
}复制代码

auto 关键字

由浏览器决定长度。通过 auto 关键字,我们可以轻易实现三列或者两列布局。grid-template-columns: 100px auto 100px 表示第一第三列为 100px,中间由浏览器决定长度,代码以及效果如下:

.wrapper{ 
    grid-template-columns: 100px auto 100px;
}复制代码

grid-row-gap 属性、grid-column-gap 属性以及 grid-gap 属性

指定网格线的大小,也可以说是网格子项之间的间距。

词法:

grid-column-gap: <line-size>

grid-row-gap: <line-size>复制代码
  • <line-size>:长度值

grid-gap是grid-column-gapgrid-row-gap的简称:

grid-gap: <grid-column-gap> <grid-row-gap>复制代码

如果只有一个值,grid-row-gap的值将和grid-column-gap一样。

实例:

.container{   

  display:grid;   

  grid-template-columns: 100px 50px 100px;   

  grid-template-rows: 80px auto 80px;    

  grid-column-gap: 10px;   

  grid-row-gap: 15px;  

}复制代码

注意:间隔仅仅作用在网格子项之间,不作用在容器边缘。

grid-template-areas 属性

grid-template-areas可以配合grid-area定义一个显式的网格区域。grid-template-areas定义网格区域,然后使用grid-area调用声明好的网格区域名称来放置对应的网格项目。

词法:

grid-template-areas: "<grid-area-name> | . | none | ..." "..." 复制代码
  • <grid-area-name>:在grid-area中指定的网格区域名字

  • .:一个句点表示一个空的网格单元

  • none:没有网格区域被定义

实例:

<div class="container">   
  <div class="item-a"></div>   
  <div class="item-b"></div>   
  <div class="item-c"></div>   
  <div class="item-d"></div>   
</div>复制代码

设置CSS样式:

.item-a{   
  grid-area: header;  
}  

.item-b{   
  grid-area: main; 
}  

.item-c{   
  grid-area: sidebar; 
}  

.item-d{   
  grid-area: footer; 
}  

.container{    
  width: 300px;
  height:200px;   
  display:grid;   
  grid-template-columns: 1fr 1fr 1fr 1fr;   
  grid-template-rows: auto;   
  grid-template-areas: "header header header header"   
                       "main main . sidebar"   
                       "header footer header footer";  
}复制代码

在上面的代码中,我们将创建一个4乘以3的网格容器,第一行由header区域组成,中间一行由 2 个main区域和1个空单元和1个sidebar区域组成,最后一行由footer区域组成。

justify-items 属性、align-items 属性

justify-items

让网格子项的内容和列轴对齐(align-items则相反,是和行轴对齐),这个值对容器里面的所有网格子项都有用。

justify-items: start | end | center | stretch复制代码
  • start:内容和网格区域的左边对齐

  • end:内容和网格区域的右边对齐

  • center:内容和网格区域的中间对齐

  • stretch:填充整个网格区域的宽度(默认值)

align-items

让网格子项的内容和行轴对齐,这个值对容器里面的所有网格子项都有用。

align-items: start | end | center | stretch;复制代码
  • start:内容和网格区域的顶部对齐

  • end:内容和网格区域的底部对齐

  • center:内容和网格区域的中间对齐

  • stretch:填充整个网格区域的高度(默认值)

justify-content 属性、align-content 属性

justify-content

如果用像px非弹性单位定义的话,总网格区域大小有可能小于网格容器,这时候你可以设置网格的对齐方式(垂直于列网格线对齐)。

justify-content: start | end | center | stretch | space-around | space-between | space-evenly ;复制代码
  • start:左对齐

  • end:右对齐

  • center:居中对齐

  • stretch:填充网格容器

  • space-around:在每个网格子项中间放置均等的空间,在始末两端只有一半大小

  • space-between:两边对齐,在每个网格子项中间放置均等的空间,在始末两端没有空间

  • space-evenly:网格间隔相等,包括始末两端

align-content

如果用像px非弹性单位定义的话,总网格区域大小有可能小于网格容器,这时候你可以设置网格的对齐方式(垂直于行网格线对齐)。

align-content: start | end | center | stretch | space-around | space-between | space-evenly 复制代码
  • start:顶部对齐

  • end:底部对齐

  • center:居中对齐

  • stretch:填充网格容器

  • space-around:在每个网格子项中间放置均等的空间,在始末两端只有一半大小

  • space-between:上下对齐,在每个网格子项中间放置均等的空间,在始末两端没有空间

  • space-evenly:在每个网格子项中间放置均等的空间,包括始末两端

grid-auto-columns 属性和 grid-auto-rows 属性

自动生成隐式网格轨道(列和行),当你定位网格项超出网格容器范围时,将自动创建隐式网格轨道。

grid-auto-columns: <track-size>

grid-auto-rows: <track-size>复制代码
  • <track-size>:可以是一个长度,百分比或者是一个网格中自由空间的份数(通过使用fr单位)

为了说明隐式网格轨迹如何被创建,思考一下这个:

.container{   
  grid-template-columns: 60px 60px;   
  grid-template-rows: 90px 90px  
}复制代码

在上面的代码中,我们创建了 2 x 2 的网格。

但现在想象你使用grid-column和grid-row(项目属性下文会讲)来定位你的网格子项,就像这样:

.item-a{   
  grid-column: 1 / 2;   
  grid-row: 2 / 3;  
}  

.item-b{   
  grid-column: 5 / 6;   
  grid-row: 2 / 3;  
}复制代码

我们告诉.item-b在第 5 列网格线开始第 6 列网格线结束,但我们还没有定义第 5 或者第 6 列。因为我们引用的线不存在,0 宽度的隐式网格轨迹将被创建来填充这些空缺。我们可以使用grid-auto-columnsgrid-auto-rows来指定这些隐式网格轨迹的宽度:

.container{   
  grid-auto-columns: 60px;  
}复制代码

grid-auto-flow 属性

grid-auto-flow 属性控制着自动布局算法怎样运作,精确指定在网格中被自动布局的元素怎样排列。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图英文数字的顺序 one,two,three...。这个顺序由 grid-auto-flow 属性决定,默认值是 row

.wrapper {
  display: grid;
  grid-template-columns: 100px 200px 100px;
  grid-auto-flow: row;
  grid-gap: 5px;
  grid-auto-rows: 50px;
}复制代码

细心的同学可能发现了一个问题,就是第五个项目和第六个项目之间有个空白(如下图所示),这个是由于第六块的长度大于了空白处的长度,被挤到了下一行导致的。在实际应用中,我们可能想让下面长度合适的填满这个空白,这个时候可以设置 grid-auto-flow: row dense,表示尽可能填满表格。代码以及效果如下所示:

image

.wrapper-2 {
  display: grid;
  grid-template-columns: 100px 200px 100px;
  grid-auto-flow: row dense;
  grid-gap: 5px;
  grid-auto-rows: 50px;
}复制代码

image

可以设置 grid-auto-flow: column,表示先列后行,代码以及效果如下图所示:

.wrapper-1 {
  display: grid;
  grid-auto-columns: 100px;
  grid-auto-flow: column;
  grid-gap: 5px;
  grid-template-rows:  50px 50px;
}复制代码

image

项目属性介绍

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

通过网格线来定义网格项的位置。grid-column-startgrid-row-start定义网格项的开始位置,grid-column-endgrid-row-end定义网格项的结束位置。

grid-column-start: <number> | <name> | span <number> | span <name> | auto ; 
grid-column-end: <number> | <name> | span <number> | span <name> | auto ;
grid-row-start: <number> | <name> | span <number> | span <name> | auto ; 
grid-row-end: <number> | <name> | span <number> | span <name> | auto ;复制代码
  • <number> | <name>:可以是一个数字以适用被标记了数字号的网格线,或者是一个名字以适用命名了的网格线

  • span <number>:子项将跨越指定数字的网格轨迹

  • span <name>:子项将跨越指定名字之前的网格线

  • auto:自动布局,自动跨越或者默认跨越一个。

实例:

.item-a{   
  grid-column-start: 2;   
  grid-column-end: five;   
  grid-row-start: row1-start   
  grid-row-end: 3  
}复制代码

.item-b{   
  grid-column-start: 1;   
  grid-column-end: span col4-start;   
  grid-row-start: 2   
  grid-row-end: span 2  
}复制代码

grid-column是grid-column-startgrid-column-end的简称;grid-rowgrid-row-startgrid-row-end的简称。

grid-column: <start-line> / <end-line> | <start-line> / span <value>;   
grid-row: <start-line> / <end-line> | <start-line> / span <value>;复制代码

实例:

.item-c{   
  grid-column: 3 / span 2;   
  grid-row: third-line / 4;  
}复制代码

grid-area 属性

给网格子项取一个名字以让它被由grid-template-areas属性创建的模板引用。同时,这个属性还可以用来更简短地表示grid-row-start+ grid-column-start + grid-row-end+ grid-column-end

grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;复制代码
  • <name>:选择的名字

  • <row-start> / <column-start> / <row-end> / <column-end> – 可以是网格线的数字或名字

实例:

作为分配一个名字给网格子项的一种方式:

.item{  

.item-d{   
  grid-area: header  
}复制代码

作为grid-row-start+ grid-column-start + grid-row-end+ grid-column-end的一种简写:

.item-d{   
  grid-area: 1 / col4-start / last-line / 6  
}复制代码

justify-self 属性、align-self 属性

(1)justify-self

让网格子项的内容以列轴对齐(与之相反align-self是跟行轴对齐),这个值可以应用在单个网格子项的内容中。

justify-self: start | end | center | stretch复制代码
  • start – 让内容在网格区域左对齐

  • end – 让内容在网格区域右对齐

  • center – 让内容在网格区域中间对齐

  • stretch – 填充着呢个网络区域的宽度(默认值)

\

(2)align-self

让网格子项的内容以行轴对齐(与之相反justify-self是跟列轴对齐),这个值可以应用在单个网格子项的内容中。

align-self: start | end | center | stretch复制代码
  • start – 让内容在网格区域上对齐

  • end – 让内容在网格区域下对齐

  • center – 让内容在网格区域中间对齐

  • stretch – 填充着呢个网络区域的高度(默认值)

记忆总结

一下子梳理了这么多属性,记住的可能没几个,我们从功能的角度来做个简单的总结,这样更有利于记忆

父容器

定框架

  • display: grid;

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

  • grid-template-areas

设间隔

  • grid-column-gap/grid-row-gap/grid-gap

找对齐

  • justify-items/align-items

  • justify-content/align-content

子项目

摆位置

  • grid-column-start/grid-column-end/grid-row-start/grid-row-end/grid-column/grid-row

找对齐

  • justify-self/align-self

取值

大小

  • 单位可以是一个长度(如px、em、rem、vw、vh)或百分比,还新引入fr容器内剩余空间的分数比;

  • min-content顾名思义是根据元素内容来设置的最小宽度大小,在英文句子中,通常是最长单词的那个长度,而中文中则是一个字的长度。

  • min-content相对应,max-content会将尺寸设置成内容尺寸能达到的最大宽度。

函数

  • minmax对于自适应的网格区域,设置一个最小值和最大值

  • repeat函数,它主要用来批量设置框架的间距,这个函数接受两个参数,第一个参数控制循环次数,第二个参数控制间距大小

  • fit-content,它实际上是min(maximum size, max(minimum size, argument))的简写,表示将元素宽度收缩到内容宽度。

命名

命名顺序同书写顺序一致:从左到右,由上至下按数字命名。假设我们指定的是3x3的网格布局结构,那么包含边框线,就会生成4+4=8条线。

对齐

用于网格布局中对齐的关键字有start,centerendstretch(默认)四个。

Grid 实战——实现响应式布局

代码演示地址

fr 实现等分响应式

fr 等分单位,可以将容器的可用空间分成想要的多个等分空间。利用这个特性,我们能够轻易实现一个等分响应式。grid-template-columns: 1fr 1fr 1fr 表示容器分为三等分

.wrapper {
  margin: 50px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}复制代码

repeat + auto-fit——固定列宽,改变列数量

等分布局并不只有 Grid 布局才有,像 flex 布局也能轻松实现,接下来看看更高级的响应式

上面例子的始终都是三列的,但是需求往往希望我们的网格能够固定列宽,并根据容器的宽度来改变列的数量。这个时候,我们可以用到上面提到 repeat() 函数以及 auto-fit 关键字。grid-template-columns: repeat(auto-fit, 200px) 表示固定列宽为 200px,数量是自适应的,只要容纳得下,就会往上排列,代码以及效果实现如下:

.wrapper {
  margin: 50px;
  display: grid;
  grid-template-columns: repeat(auto-fit, 200px);
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}复制代码

repeat+auto-fit+minmax 去掉右侧空白

上面看到的效果中,右侧通常会留下空白,这是我们不希望看到的。如果列的宽度也能在某个范围内自适应就好了。minmax() 函数就帮助我们做到了这点。将 grid-template-columns: repeat(auto-fit, 200px) 改成 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) 表示列宽至少 200px,如果还有空余则一起等分。代码以及效果如下所示:

.wrapper {
  margin: 50px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}


作者:夏茉薇薇
链接:https://juejin.cn/post/7031445725875699719


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐