Grid网格布局学习
引言
本文不对grid布局由来以及优劣做过多的介绍,仅介绍grid网格布局的用法及其效果显示
部分说明图片引用http://chris.house/blog/a-complete-guide-css-grid-layout/和http://blog.jirengu.com/?p=990
浏览器支持情况
从2017年起,许多浏览器都提供了原生的、不加前缀的对CSS Grid的支持,比如 Chrome(包括Android),Firefox,Safari(包括iOS)和Opera。
具体浏览器支持可查询https://caniuse.com/#feat=css-grid
基本术语介绍
Grid Container
设置了 display: gird
的元素。 这是所有 grid item 的直接父项。下面例子的.container
就是是 grid container
<div class="container">
<div class="item item-1"></div>
<div class="item item-2"></div>
<div class="item item-3"></div>
</div>
Grid Item
Grid 容器的孩子(直接子元素)。下面的 .item
元素就是 grid item,但 .sub-item
不是。
<div class="container">
<div class="item"></div>
<div class="item">
<p class="sub-item"></p>
</div>
<div class="item"></div>
</div>
Grid Line
网格线:网格和网格之间的分界线,可以是行线也可以是列线
Grid Track
网格轨迹:两条行线与行线或列线与列线之间的空间
Grid Cell
网格单元:两个相邻的行和两个相邻的列网格线之间的空间。它是网格的一个“单元”。 下面是行网格线1和2之间以及列网格线2和3的网格单元
Grid Area
网格区域:四个网格线包围的总空间。 网格区域可以由任意数量的网格单元组成。 下面是行网格线1和3以及列网格线1和3之间的网格区域。
Grid 属性列表
Grid 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
- justify-content
- align-content
- grid-auto-columns
- grid-auto-rows
- grid-auto-flow
- grid
Grid Items 的全部属性
- grid-column-start
- grid-column-end
- grid-row-start
- grid-row-end
- grid-column
- grid-row
- grid-area
- justify-self
- align-self
父容器(Grid Container)的属性
display
声明元素grid网格布局
- grid – 生成一个块级(block-level)网格
- inline-grid – 生成一个行级(inline-level)网格
- subgrid – 如果你的 grid container 本身就是一个 grid item(即,嵌套网格),你可以使用这个属性来表示你想从它的父节点获取它的行/列的大小,而不是指定它自己的大小。
.container {
display: grid | inline-grid | subgrid;
}
grid-template-columns / grid-template-rows
使用以空格分隔的多个值来定义网格的列和行。这些值表示轨道大小(track size),它们之间的空格代表表格线(grid line)。
.container {
grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}
使用[]
给网格线命名,轨道值之间仅仅有空格时,网格线会被自动分配数字名称,而且一个网格线可以有多个名字,名字与名字之间用空格相隔[row1-end row2-start]
eg:
.container {
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end row2-start] 100px [third-line] auto [last-line];
}
如果你的定义中包含重复的部分,则可以使用
repeat()
符号来简化写法:.container { grid-template-columns: repeat(3, 20px [col-start]) 5%; }
上面的写法和下面等价:
.container { grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%; }
“fr”单位允许您将轨道大小设置为网格容器自由空间的一部分
例如以下:fr单位可用的自由空间总量不包括50px,将剩余的自由空间平分:
.container {
grid-template-columns: 1fr 50px 1fr 1fr;
}
grid-template-areas
通过引用 grid-area
属性指定的网格区域的名称来定义网格模板。 重复网格区域的名称导致内容扩展到这些单元格。 点号表示一个空单元格。
-
<grid-area-name>
– 使用 grid-area 属性设置的网格区域的名称 -
.
– 点号代表一个空网格单元 - none – 没有定义网格区域
<div class="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
</div>
.item-1 {
background-color: red;
grid-area: num1;
}
.item-2 {
background-color: greenyellow;
grid-area: num2;
}
.item-3 {
background-color: blue;
grid-area: num3;
}
.item-4 {
background-color: gray;
grid-area: num4;
}
.container {
width: 300px;
height: 300px;
display: grid;
/* 确定行列空间 可以使用auto */
grid-template-rows: 100px 100px 100px;
grid-template-columns: 100px 100px 100px;
}
注意:相同命名区域不可跨行和跨列
同样 grid-area
属性也可以指定网格线区域来划定范围
.item-2 {
background-color: greenyellow;
grid-area: 1 / 1 / 3 / 3;
}
grid-template
在单个声明中定义 grid-template-rows、grid-template-columns、grid-template-areas 的简写。
值:
- none – 将三个属性都设置为其初始值
- subgrid – 把 grid-template-rows 和 grid-template-columns 设置为 subgrid, 并且 grid-template-areas 设置为初始值
-
grid-template-rows
/<grid-template-columns
– 把 grid-template-columns 和 grid-template-rows 设置为指定值, 与此同时, 设置 grid-template-areas 为 none
.container {
grid-template: none | subgrid | <grid-template-rows> / <grid-template-columns>;
}
grid-column-gap / grid-row-gap
指定网格线的大小,你可以把它想象为设置列/行之间的间距的宽度。
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-column-gap: 10px;
grid-row-gap: 15px;
}
只能在列/行之间创建缝隙,而不是在外部边缘创建。
grid-gap
grid-row-gap 和 grid-column-gap 的缩写
justify-items和align-items
强调:flex布局中并没有justify-items属性,请勿弄混淆;本人认为可能是因为flex布局存在flex-grow和flex-shrink属性
补充:flex布局可参考http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
沿着行轴对齐网格内的内容(与之对应的是 align-items, 即沿着列轴对齐),该值适用于容器内的所有的 grid items。
值:
- start: 内容与网格区域的左端对齐
- end: 内容与网格区域的右端对齐
- center: 内容位于网格区域的中间位置
- stretch: 内容宽度占据整个网格区域空间(这是默认值)
.container {
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
}
注意:没有确定item的宽高时默认宽高都是stretch状态,即充满整个单元格
沿着行轴对齐网格
.container {
justify-items: start;
}
.container{
justify-items: end;
}
.container {
justify-items: center;
}
.container {
justify-items: stretch;
}
也可以通过给单个 grid item 设置justify-self
属性来达到上述效果。
沿着列轴对齐网格
.container {
align-items: start;
}
.container {
align-items: end;
}
.container {
align-items: center;
}
.container {
align-items: stretch;
}
也可以通过给单个 grid item 设置align-self
属性来达到上述效果。
justify-content和align-content
内容所占区域相对于网格容器的排列方式,justify-content沿着行轴对齐网格(与之对应的是 align-content, 沿着列轴对齐)。
值:
- start – 网格与网格容器的左边对齐
- end – 网格与网格容器的右边对齐
- center – 网格与网格容器的中间对齐
- stretch – 调整g rid item 的大小,让宽度填充整个网格容器
- space-around – 在 grid item 之间设置均等宽度的空白间隙,其外边缘间隙大小为中间空白间隙宽度的一半
- space-between – 在 grid item 之间设置均等宽度空白间隙,其外边缘无间隙
- space-evenly – 在每个 grid item 之间设置均等宽度的空白间隙,包括外边缘
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
.container { justify-content: start;}
.container {
justify-content: end;
}
.container {
justify-content: center;
}
.container {
justify-content: stretch;
}
.container {
justify-content: space-around;
}
.container {
justify-content: space-between;
}
.container {
justify-content: space-evenly;
}
.container {
align-content: start;
}
.container {
align-content: end;
}
.container {
align-content: center;
}
.container {
align-content: stretch;
}
.container {
align-content: space-around;
}
.container {
align-content: space-between;
}
.container {
align-content: space-evenly;
}
grid-auto-columns / grid-auto-rows
指定自动生成的网格轨道(又名隐式网格轨道)的大小。 隐式网格轨道在你显式的定位超出指定网格范围的行或列(使用 grid-template-rows/grid-template-columns)时被创建。
值:
-
<track-size>
– 可以是一个长度值,一个百分比值,或者一个自由空间的一部分(使用 fr 单位)
.container {
grid-auto-columns: <track-size> ...;
grid-auto-rows: <track-size> ...;
}
通俗的讲:如果有一个2X2的容器,你将一个单元格定位到了2行5列的位置,则第4列和第5列被称为隐式轨道,默认情况下为0
现在通过设置grid-auto-columns
改变隐式轨道的宽度
.container {
grid-auto-columns: 60px;
}
grid-auto-flow
控制自动布局算法的布局方式。
值:
- row – 告诉自动布局算法依次填充每行,根据需要添加新行
- column – 告诉自动布局算法依次填充每列,根据需要添加新列
- dense – 告诉自动布局算法,如果后面出现较小的 grid item,则尝试在网格中填充空洞
.container {
grid-auto-flow: row | column | row dense | column dense
}
需要注意的是,dense
可能导致您的 grid item 乱序。
工作方式为:先在网格中放置有明确定位的定位元素( 即 有明确的行或列定位 ),在按照grid-auto-flow
属性的排列方式对 空白区域 进行排列元素
举例:
创建一个5*5的网格容器
<div class="wrapper">
<div class="box a">A1</div>
<div class="box b">B2</div>
<div class="box c">C3</div>
<div class="box d">D4</div>
<div class="box e">E5</div>
<div class="box f">F6</div>
<div class="box h">H7</div>
<div class="box i">I8</div>
<div class="box j">J9</div>
<div class="box k">K10</div>
<div class="box l">L11</div>
<div class="box m">M12</div>
<div class="box n">N13</div>
<div class="box o">O14</div>
</div>
定位b元素区域为第2行到第4行,第3列到第6列区域;
.b {
grid-column: 3 / 6;
grid-row: 2 / 4;
outline: 2px solid red;
}
若将e元素有明确定位到第2行到第4行,第1列到第3列
// 方式1:确定行和列
.e{
grid-column: 1 / 3;
grid-row: 2 / 4;
background-color: #ffa94d;
}
// 方式2:确定行或列 span扩展
.e{
grid-column: 1 / span 2;
grid-row: 2 / span 2;
background-color: #ffa94d;
}
效果
若e元素没有明确定位而只是规定了大小呢?
.wrapper .e {
grid-column-end: span 2;
grid-row-end: span 2;
}
效果
出现这两种排列现象的原因是什么?
因为在e元素有明确定位的时候浏览器会先将有定位的元素(如b和e)优先排列在网格中,将剩下的元素从网格的起始位置开始排列放入空的网格中
若e并没有明确定位的时候,e和其他没有明确定位元素一样(如a)只是e所占空间为4格,浏览器只会现将有定位元素的b放入网格中,再将a,b,c,d元素依次放入空白网格,当放置e元素时,d后面只有一个单元格放置不下b,此时e将会往下一行(未设置grid-auto-flow属性默认为row)寻找所能容纳的区域,中间空白保留。
若要想填充空白区域可设置grid-auto-flow: row dense
,浏览器会自动计算可以填充的元素自动填充到空白区域
效果
如果设置grid-auto-flow为column将会遵循一列一列排列
孩子(Grid Items)的属性
grid-column-start / grid-column-end / grid-row-start /grid-row-end
使用特定的网格线确定 grid item 在网格内的位置。grid-column-start/grid-row-start 属性表示grid item的网格线的起始位置,grid-column-end/grid-row-end属性表示网格项的网格线的终止位置。
值:
-
<line>
: 可以是一个数字来指代相应编号的网格线,也可使用名称指代相应命名的网格线 -
span <number>
: 网格项将跨越指定数量的网格轨道 -
span <name>
: 网格项将跨越一些轨道,直到碰到指定命名的网格线 - auto: 自动布局, 或者自动跨越, 或者跨越一个默认的轨道
.item {
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
}
grid-column / grid-row
grid-column-start + grid-column-end, 和 grid-row-start + grid-row-end 的简写形式。
值:
-
<start-line>
/<end-line>
– 每个值的用法都和属性分开写时的用法一样
.item {
grid-column: <start-line> / <end-line> | <start-line> / span <value>;
grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}
grid-area
给 grid item 进行命名以便于使用 grid-template-areas 属性创建模板时来进行引用。另外也可以做为 grid-row-start + grid-column-start + grid-row-end + grid-column-end 的简写形式。
值:
-
<name>
– 你的命名 -
<row-start>
/<column-start>
/<row-end>
/<column-end>
– 可以是数字,也可以是网格线的名字
.item {
grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
justify-self和align-self
沿着行轴对齐grid item 里的内容(与之对应的是 align-self, 即沿列轴对齐)。 此属性对单个网格项内的内容生效。
值:
- start – 将内容对齐到网格区域的左端
- end – 将内容对齐到网格区域的右端
- center – 将内容对齐到网格区域的中间
- stretch – 填充网格区域的宽度 (这是默认值)