grid 网格布局(grid网格布局兼容性)
引入
对于Web开发者来说,网页布局一直是个比较重要的问题。但实际上,在网页开发很长的一段时间当中,我们甚至没有一个比较完整的布局模块。总的来说 Web 布局经历了以下四个阶段:
1、table表格布局,通过 Dreamweaver 拖拽表格或者手写 table 标签布局
2、float浮动及position定位布局,借助元素元素盒模型本身的特性以及 float position 等属性等进行布局
3、flex弹性盒模型布局,革命性的突破,解决传统布局方案上的三大痛点 排列方向、对齐方式,自适应尺寸。是目前最为成熟和强大的布局方案
4、grid栅格布局,二维布局模块,具有强大的内容尺寸和定位能力,适合需要在两个维度上对齐内容的布局
什么是 grid 布局
Grid
布局即网格布局,是一种新的 CSS
布局模型,比较擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。号称是最强大的的 CSS
布局方案,是目前唯一一种 CSS
二维布局。利用 Grid
布局,我们可以轻松实现类似下图布局,演示地址
Grid 布局和 flex 布局
讲到布局,我们就会想到 flex
布局,甚至有人认为竟然有 flex
布局了,似乎没有必要去了解 Grid
布局。但 flex
布局和 Grid
布局有实质的区别,那就是 flex
布局是一维布局,Grid
布局是二维布局。flex
布局一次只能处理一个维度上的元素布局,一行或者一列。Grid
布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到我们布局的目的。
所以Grid
更适合页面宏观的架构搭建,flex
更擅长局部行列布局。
flex布局示例:
Grid 布局示例:
Grid 布局兼容性
最后,聊聊 Grid
布局兼容性问题,在 caniuse 中,我们可以看到的结果如下,总体兼容性还不错,但在 IE 10 以下不支持。个人建议在公司的内部系统运用起来是没有问题的,但 TOC 的话,可能目前还是不太合适
Grid 的一些基础概念
网格布局是一种二维布局结构,它是由纵横相交的两组网格线形成的框架性布局结构。网页设计者可以利用这些由行(row)和列(column)形成的框架性结构来布局设计元素。 在定义一种网格布局结构的时候,我们需要在父容器上描述要布局的主体框架结构。为了描述这一框架结构,我们就需要给它的基本构成元素命名。一个网格布局的构成元素可以概括为以下几种概念:
row line: 行线
column line: 列线
track: 网格轨道,即行线和行线,或列线和列线之间所形成的区域,用来摆放子元素
gap: 网格间距,行线和行线,或列线和列线之间所形成的不可利用的区域,用来分隔元素
cell: 网格单元格,由行线和列线所分隔出来的区域,用来摆放子元素
area: 网格区域,由单个或多个网格单元格组成,用来摆放子元素!
牢记上述这些概念是之后熟练掌握和应用网格布局的基础。
容器属性介绍
虽然网格布局好处有很多,但学习起来并不简单,原因是用来设置布局的属性实在太多,其中光是作用于父容器的属性就有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; }复制代码
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-gap
和grid-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-columns
和grid-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
,表示尽可能填满表格。代码以及效果如下所示:
.wrapper-2 { display: grid; grid-template-columns: 100px 200px 100px; grid-auto-flow: row dense; grid-gap: 5px; grid-auto-rows: 50px; }复制代码
可以设置 grid-auto-flow: column
,表示先列后行,代码以及效果如下图所示:
.wrapper-1 { display: grid; grid-auto-columns: 100px; grid-auto-flow: column; grid-gap: 5px; grid-template-rows: 50px 50px; }复制代码
项目属性介绍
grid-column-start/grid-column-end/grid-row-start/grid-row-end/grid-column/grid-row
通过网格线来定义网格项的位置。grid-column-start
、grid-row-start
定义网格项的开始位置,grid-column-end
、grid-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-start
和grid-column-end
的简称;grid-row
是grid-row-start
和grid-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
,center
, end
和stretch
(默认)四个。
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