Grid简介
CSS Grid Layout
(又叫Grid
或者CSS Grid
),它是一个二维网格的布局系统。在这之前经过了tables
,float
,positioning
和inline-block
,但它们都相当于一个
hack,并且功能较少。Flex
布局虽然是一个很棒的布局工具,但它是一维的,只能分开操作行和列。
Grid术语
Grid Container(容器)
当你对一个元素设置了display:grid
后,它就是一个grid容器,如下:
<style>
.container {
display: grid
}
</style>
<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容器后,该容器的所有直接子标签都是grid项目。这和flex布局是一样的
Grid Line(网格线)
它是构成grid布局的分界线。它们既可以是水平的(row grid lines)
也可以是垂直的(column grid lines)
Grid Cell(网格单元)
由两条相邻的row grid lines(行)
和两条相邻的column grid lines(列)
组成的一个单元
Grid Track(网格轨道)
两条相邻网格线之间的空间。可以把它们看成网格的列或行。这里是第二行和第三行网格线之间的网格轨道
Grid Area(网格域)
由四条网格线组成的总空间,它可以由任意数量的grid cells
组成
CSS Grid 容器中可用的属性
display
定义一个元素作为grid container并创建一个单列多行的grid formatting context(网格格式化上下文GFC)
, 行数由容器内的子元素(包括微元素和文本节点)决定
值:
- grid - 生成一个块级grid
inline-grid - 生成一个内联grid
display: grid | inline-grid
grid-template-columns 、 grid-template-rows
该属性定义的网格是一个显式网格, 使用
grid-template-columns
和grid-template-rows
属性定义网格的行和列(网格轨道), 都使用 空格分隔多个数值, 这些值代表网格轨道的大小,而且数值间的空格代表网格线
比如在容器上只显式设置grid-template-columns
,那么grid-template-rows
则默认为auto
<style>
* {
margin: 0;
padding: 0;
}
.container {
display: grid;
grid-template-columns: 180px 20% auto 1fr 10vw;
}
.item {
height: 100px;
}
.item1 {
background: #e7c98c;
}
.item2 {
background: #a21eee;
}
.item3 {
background: #e690dd;
}
.item4 {
background: #a7b7c7;
}
.item5 {
background: #23cccc;
}
.item6 {
background: #5fddc3;
}
</style>
<div class="container">
<div class="item item1">grid cell 1</div>
<div class="item item2">grid cell 2</div>
<div class="item item3">grid cell 3</div>
<div class="item item4">grid cell 4</div>
<div class="item item5">grid cell 5</div>
<div class="item item6">grid cell 6</div>
</div>
效果如图:
则表示定义了一个5列N行的网格,即将网格容器分为5列,每列宽度分别为180px
,20%
,auto
,1fr
,10vw
等不同单位的值。
当多再添加一个网格项目时,则会创建5列2行的网格,如图:
然后在上面代码的基础上使用grid-template-rows
显式指定网格轨道的尺寸,同时也会定义出轨道的数量(该属性的轨道指的就是行
)
.container {
display: grid;
grid-template-columns: 180px 20% auto 1fr 10vw;
grid-template-rows: 200px minmax(100px, auto) 20vh;
}
这里就指定了一个5列3行的网格,即使是不满足有15个项目
同时,如果网格项目
超过了你创建的网格单元
数量,将会重新创建新的一行网格轨道
,并以auto
来计算网格轨道尺寸(又叫隐式网格
)。
在使用grid-template-columns
和grid-template-rows
时,默认会使用数字来指出网格线。按以上的代码为例,从左往右的column grid lines
为1 ~ 6,从右往左为-1 ~ -6,从上往下的row grid lines
为1~4, 从下往上为-1 ~ -4。
当然,也可以自己命名
.container {
display: grid;
grid-template-columns:[line1] 180px [line2] 20% [line3] auto [line4] 1fr [line5] 10vw [line6];
grid-template-rows: [row1] 200px [row2] minmax(100px, auto) [row3] 20vh [row4];
}
同样,一条网格线也可以有多个名称
.container {
grid-template-rows: [row1-start] 200px [row1-end row2-start] minmax(100px, auto) [row2-end row3-start] 20vh [row3-end];
}
为什么需要命名呢?因为想要创建一个符合需求的web布局,还需要网格项目属性grid-colunm
,grid-row
,grid-area
指定内容所占网格域
。这几个属性都是根据网格线的名称来指定网格域
的所占空间,所以主要是为了可读性。比如定义一个如下的圣杯布局,如果用数字来确认内容的网格域
,是不是很乱?
<style>
* {
margin: 0;
padding: 0;
}
.container {
display: grid;
grid-template-columns:
[header-col-start nav-col-start footer-col-start] 220px
[nav-col-end main-col-start] 1fr
[main-col-end aside-col-start] 200px
[header-col-end aside-col-end footer-col-end];
grid-template-rows:
[header-row-start] 80px
[header-row-end nav-row-start main-row-start aside-row-start] 400px
[footer-row-start nav-row-end main-row-end aside-row-end] 80px
[footer-row-end];
}
header {
background: #e287ea;
grid-column: header-col-start / header-col-end;
grid-row: header-row-start/ header-row-end;
}
nav {
background: #87eeee;
grid-column: nav-col-start / nav-col-end;
grid-row: nav-row-start/ nav-row-end;
}
main {
background: #7633ae;
grid-column: main-col-start / main-col-end;
grid-row: main-row-start/ main-row-end;
}
aside {
background: #ee323a;
grid-column: aside-col-start / aside-col-end;
grid-row: aside-row-start/ aside-row-end;
}
footer {
background: #e67;
grid-column: footer-col-start / footer-col-end;
grid-row: footer-row-start/ footer-row-end;
}
</style>
<div class="container">
<header>header</header>
<main>Main</main>
<nav>Nav</nav>
<aside>aside</aside>
<footer>footer</footer>
</div>
效果如下
grid-template-areas
不同于以上的grid-template-columns
和grid-template-rows
,使用grid-template-areas
同样也可以显式的创建一个网格布局,并且该语法使得网格结构更加的可视化,还不需要再命名网格线。我们还是以上面的圣杯布局为例,代码如下
<style>
* {
margin: 0;
padding: 0;
}
.container {
height: 100vh;
display: grid;
grid-template-columns: 220px 1fr 200px;
grid-template-rows: 80px 1fr 80px;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
}
header {
grid-area: header;
background: #e287ea;
}
nav {
grid-area: nav;
background: #87eeee;
}
main {
grid-area: main;
background: #7633ae;
}
aside {
grid-area: aside;
background: #ee323a;
}
footer {
grid-area: footer;
background: #e67;
}
</style>
<div class="container">
<header>header</header>
<main>Main</main>
<nav>Nav</nav>
<aside>aside</aside>
<footer>footer</footer>
</div>
页面效果如下:
且使用这属性必须要遵循以下规则
- 描述完整的网格结构
- 使用
.
来标记一个空的grid cell
- 使用
none
表示没有定义grid areas
column-gap、grid-column-gap、row-gap、grid-row-gap
用于定义两个grid项目之间的间距,可以用任意css长度单位
.container {
/* standard */
column-gap: 10px | 1rem | 1vw;
row-gap: 10px | 1rem | 1vw;
/* old */
grid-column-gap: 10px | 1rem | 1vw;
grid-row-gap: 10px | 1rem | 1vw;
}
gap、grid-gap
是以上属性的简写,如果只定义了一个value,那么row-gap
和column-gap
都会采用该值
.container {
/* standard */
gap: <row-gap> <column-gap>;
/* old */
grid-gap: <grid-row-gap> <grid-column-gap>;
}
justify-items
沿着水平方向的轴线对齐网格项目,这个值适用于容器内的所有网格项目。
如果不设置该值,默认会拉伸所有的gird项目
至grid cell
的大小
让项目在网格的起始位置对齐
.container { justify-items: start; }
- 让项目在网格的结束位置对齐
.container { justify-items: end; }
- 让项目在网格的中间位置对齐
.container {
justify-items: center;
}
拉伸项目至网格宽度
.container { justify-items: stretch; }
align-items
该属性基本与justify-items
相同,只不过对齐的方式相反,这个属性沿着竖直方向的轴线对齐网格项目。
沿竖直方向在网格(网格域)的开始位置对齐
.container { align-items: start; }
沿竖直方向在网格的结束位置对齐
.container { align-items: end; }
- 沿竖直方向在网格的中间位置对齐
.container { align-items: center;}
- 沿竖直方向拉伸项目至网格的高度
.container { align-items: stretch;}
justify-content
和flex的一样,用于设置水平方向网格的对齐方式。即当网格总尺寸小于容器尺寸时使用
- 沿着容器的水平方向,对齐网格
.container { justify-content: start; }
2.沿容器的水平方向的结束位置,对齐网格
.container { justify-content: end; }
沿容器的水平方向的中间位置,对齐网格
.container { justify-content: center; }
- 沿容器的水平方向拉伸网格
比如设置grid-template-columns: 100px auto 100px
,第二列的网格没有设置一个固定尺寸,然后再设置以下的值(该值为默认值),则会拉伸。如果设置的是固定尺寸(px),则无法拉伸
.container { justify-content: stretch;}
沿容器的水平方向均匀分配剩余空间,项目与项目间的间隔距离比项目与容器边框的距离大1倍
.container { justify-content: space-around; }
- 沿容器水平方向两边排列项目
.container { justify-content: space-between; }
和space-around类似,不过该值无论是项目与项目间的间隔距离还是项目与容器边框的距离都会均匀分配
.container { justify-content: space-evenly; }
align-content
与justify-content相反,用于设置竖直方向grid cell的对齐方式。即当grid cell总尺寸小于grid container时使用
- 沿着容器的竖直方向,对齐网格
.container { align-content: start; }
2.沿容器的竖直方向的结束位置,对齐网格
.container { align-content: end; }
沿容器的竖直方向的中间位置,对齐网格
.container { justify-content: center; }
- 沿容器的竖直方向拉伸网格
比如设置grid-template-rows: 100px auto 100px
,第行列的网格没有设置一个固定尺寸,然后再设置以下的值(该值为默认值),则会拉伸。如果设置的是固定尺寸(px),则无法拉伸
.container { align-content: stretch;}
沿容器的竖直方向均匀分配剩余空间,项目与项目间的间隔距离比项目与容器边框的距离大1倍
.container { align-content: space-around; }
- 沿容器竖直方向两边排列项目
.container { align-content: space-between; }
和space-around类似,不过该值无论是项目与项目间的间隔距离还是项目与容器边框的距离都会均匀分配
.container { align-content: space-evenly; }
应用在grid项目上的属性
grid-column-start、grid-column-end、grid-row-start、grid-row-end
以上这几个属性用于控制项目的位置以及项目所占网格大小,还是用之前的圣杯布局做例子,
代码如下:
<style>
* {
margin: 0;
padding: 0;
}
.container {
display: grid;
height: 100vh;
grid-template-columns:
[header-start nav-start footer-start] 220px
[nav-end main-start ] 1fr
[main-end aside-start] 220px
[header-end aside-end footer-end];
grid-template-rows:
[header-start] 80px
[header-end nav-start main-start aside-start] 1fr
[nav-end main-end aside-end footer-start] 80px
[footer-end];
}
header {
grid-column-start: header-start;
grid-column-end: header-end;
grid-row-start: header-start;
grid-row-end: header-end;
background: #e287ea;
}
nav {
grid-column-start: nav-start;
grid-column-end: nav-end;
grid-row-start: nav-start;
grid-row-end: nav-end;
background: #87eeee;
}
main {
grid-column-start: main-start;
grid-column-end: main-end;
grid-row-start: main-start;
grid-row-end: main-end;
background: #7633ae;
}
aside {
grid-column-start: aside-start;
grid-column-end: aside-end;
grid-row-start: aside-start;
grid-row-end: aside-end;
background: #ee323a;
}
footer {
grid-column-start: footer-start;
grid-column-end: footer-end;
grid-row-start: footer-start;
grid-row-end: footer-end;
background: #e67;
}
</style>
<div class="container">
<header>header</header>
<main>Main</main>
<nav>Nav</nav>
<aside>aside</aside>
<footer>footer</footer>
</div>
可以看到,代码量非常的大,所以不推荐使用,如果要使用这种方法,可以用下面的简写方式。
grid-column、grid-row
该属性是以上属性的简写方式,语法如下
.item {
grid-column: <start-line> / <end-line> | <start-line> / span <value>;
grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}
值既可以使用默认的数值,也可以使用自定义的网格线名称,或者混用
具体代码示例可看之前的圣杯布局
grid-area(推荐写法)
它是以上属性的更加简写方式,需要配合grid-template-areas
定义可视化的网格布局,然后来指定网格域。
具体示例也在之前的圣杯布局中有使用
justify-self
- 使网格项目按水平方向沿网格单元开始处排列
.item-a { justify-self: start; }
使网格项目按水平方向沿网格单元结束处排列
.item-a { justify-self: end; }
使网格项目按水平方向沿网格单元中间处排列
.item-a { justify-self: center; }
使网格项目拉伸至单元格水平方向的尺寸
.item-a { justify-self: stretch; }
align-self
该属性和justify-self
基本一致,只不过是竖直方向
place-self
该值为justify-self
和align-self
的简写模式
.item-a {
place-self: <align-self> / <justify-self>
}
fr单位
fr
只能用于网格布局中,如grid-template-columns
,grid-template-rows
等属性上。
它的工作方式和flex-grow
类似,根据网格容器中的可用空间比例来调整网格轨道大小。如下示例:
<style>
* {
margin: 0;
padding: 0;
}
.container {
display: grid;
height: 100vh;
grid-template-columns: 20fr 50fr 30fr;
grid-template-rows: repeat(2, 50fr);
}
.item1 {
background: #e7c98c;
}
.item2 {
background: #a21eee;
}
.item3 {
background: #e690dd;
}
.item4 {
background: #a7b7c7;
}
.item5 {
background: #23cccc;
}
.item6 {
background: #5fddc3;
}
</style>
<div class="container">
<div class="item item1">grid cell 1</div>
<div class="item item2">grid cell 2</div>
<div class="item item3">grid cell 3</div>
<div class="item item4">grid cell 4</div>
<div class="item item5">grid cell 5</div>
<div class="item item6">grid cell 6</div>
</div>
由此可以得出:网格宽度 = 网格轨道fr系数 * (剩余空间 / 总fr数量)
而且不同于设置百分比
,使用fr
再设置gap
并不会溢出容器,全部使用百分比
设置网格宽度容易导致溢出容器
grid布局中的函数
repeat()函数
接收两个参数:
- 参数一:表重复次数,如
grid-template-rows: repeat(3, 1fr)
就等于grid-template-rows: 1fr 1fr 1fr
,或者填写auto-fit
和auto-fill
关键词 - 参数二:为需要重复的值(可以为一个列表值或符合值),如
grid-template-rows: repeat(3, 1fr 200px)
就等于grid-template-rows: 1fr 200px 1fr 200px
当第一个参数使用关键词时,会更加多变。
auto-fill
在一行中尽可能的创建更多的列。只要能容纳新的列,就会自动创建隐式列,代码如下:
<style>
* {
margin: 0;
padding: 0;
}
.container {
display: grid;
height: 100vh;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-template-rows: repeat(2, 50fr);
}
.item1 {
background: #e7c98c;
}
.item2 {
background: #a21eee;
}
.item3 {
background: #e690dd;
}
.item4 {
background: #a7b7c7;
}
.item5 {
background: #23cccc;
}
.item6 {
background: #5fddc3;
}
</style>
<div class="container">
<div class="item item1">grid cell 1</div>
<div class="item item2">grid cell 2</div>
<div class="item item3">grid cell 3</div>
<div class="item item4">grid cell 4</div>
<div class="item item5">grid cell 5</div>
<div class="item item6">grid cell 6</div>
</div>
从图中可以看出多创建了两个列(数量不是固定的)
auto-fit
根据当前已有的项目创建列,如果容器还有剩余空间,则将剩余空间均分给现有的列,自动变宽填满整个容器。当容器没有可用空间时另起一行,我们把上面的代码改一下
.container {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
这时候,就不会创建更多的列,而是让每列平分剩余空间
minmax(MIN, MAX)
输出一个范围值,定义一个大于或等于MIN
且小于或等于MAX
的值的尺寸范围
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。