共计 10487 个字符,预计需要花费 27 分钟才能阅读完成。
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
的值的尺寸范畴
参考资料
- https://css-tricks.com/snippets/css/complete-guide-grid/
- https://juejin.cn/book/7161370789680250917