网格介绍
CSS 网格布局帮助你轻松实现复杂的 Web 设计。它通过把 HTML 元素转换为具有行和列的网格容器,以便将子元素放置在所需要的位置。
CSS 网格布局是CSS中功能最强大的布局系统。它是一个二维系统,这意味着它既可以处理列又可以处理行,而 flexbox 很大程度上是一维系统。通过将CSS规则应用于父元素(成为 Grid 容器)和该元素的子元素(成为 Grid Items),使用 Grid 布局。
注意: Flexbox布局最适合应用程序的组件和小规模布局,而Grid布局则用于较大规模的布局。
网格背景
CSS网格布局(又称“网格”)是基于二维网格的布局系统,旨在完全改变我们设计基于网格的用户界面的方式。
在早期的CSS网页布局中,我们使用tabel,浮动,定位和inline-block的效果都不是很好,因为这些所有方法本质上都是hack,并且遗漏了许多重要功能(例如,垂直居中)。Flexbox提供了帮助,但它适用于更简单的一维布局,而不是复杂的二维布局(Flexbox和Grid实际上可以很好地协同工作)。Grid是专门为解决布局问题而创建的第一个CSS模块。
网格概念
使用网格布局你必须定义一个网格容器元素,设置列和行的大小,然后将其子元素融入到网格列与行中。与flexbox相似,网格项目的原顺序无关紧要。你的CSS可以按任何顺序放置它们,这使得通过媒体查询重新排列网格非常容易。想象一下定义整个页面的布局,然后完全重新排列它以适应不同的屏幕宽度,而只需要几行CSS。网格是有史以来功能最强大的CSS模块之一。
重要术语
网格容器 (Grid Container)
网格容器就是将属性display的值设为grid 的HTML 元素
.container {
display: grid;
}
网格项 (Grid Item)
网格容器的子代(即直接后代)。这里的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 Cell)
两个相邻的行和两个相邻的列网格线之间的空间。它是网格的单个“单元”。这是行网格线1和2和列网格线2和3之间的网格单元。
网格轨迹 (Grid Track)
两条相邻的网格线之间的间隔。您可以将它们视为网格的列或行。这是第二行和第三行网格线之间的网格轨迹。
网格区域 (Grid Area)
四格线包围的总空间。网格区域可以由任意数量的网格单元组成。这是行网格线1和3以及列网格线1和3之间的网格区域。
网格容器的属性
display
将元素定义为网格容器,并为其内容建立新的网格格式上下文。
.container {
display: grid | inline-grid;
}
- grid:生成块级网格
- inline-grid:生成内联级网格
grid-template-columns
通过使用 grid-template-columns 添加多列,该属性值的数量表示网格的列数,而每个值表示对应列的宽度。
grid-template-rows
通过使用 grid-template-rows 添加多行,该属性值的数量表示网格的行数,而每个值表示对应行的高度。
.container {
grid-template-columns: 值1 值2 值3;
grid-template-rows: 值1 值2 值3;
}
注意:grid-template-rows 与 grid-template-columns 接受的值中包含两个数据
- track-size: 可以是网格中可用空间的长度,百分比或分数(使用fr单位)
- line-name:自定义网格线名称
案例一:隐式命名
.container {
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}
案例二:显式命名(网格线需要括号包裹)
.container {
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];
}
案例三:网格线设置多个名称
.container {
grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}
使用 CSS 网格单位来更改列和行的大小:
在 CSS 网格中,可以使用绝对定位和相对定位单位如px和em来确定行或列的大小。下面的单位也可以使用:
- fr:设置列或行占剩余空间的一个比例,
- auto:设置列宽或行高自动等于它的内容的宽度或高度,
- %:将列或行调整为它的容器宽度或高度的百分比,
.container {
grid-template-columns: auto 50px 10% 2fr 1fr 1fr;
}
上面这段代添加了六个列。第一列的宽与它的内容宽度相等;第二列宽 50px;第三列宽是它容器的 10%;最后三列,将剩余的宽度平均分成四份,第四列占两份,第五列占一份,第六列占一份。
grid-template-areas(区域模板)
你可以将网格中的一些网格单元格组合成一个区域(area),并为该区域指定一个自定义名称,语法本身提供了网格结构的可视化。你可以通过给容器加上grid-template-areas来实现:
自定义名称可选值:
- grid-area-name: grid-area属性(网格项)指定的网格区域的名称
.
句号: 表示一个空的网格单元- none: 未定义网络区域
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}
.container {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: auto 50px auto;
grid-template-areas:
"header header header header"
"main main . sidebar"
"footer footer footer footer";
}
这将创建一个四列宽,三行高的网格。整个第一行将由标题区域组成。中间行将由两个主要区域组成,一个为空白单元格,另一个为侧边栏区域。最后一行都是页脚。
在代码中,每个单词代表一个网格单元格,每对引号代表一行。
声明中的每一行都必须具有相同数量的单元格。
您可以使用任意数量的相邻
.
句号来声明一个空单元格。只要句点之间没有空格,它们就代表一个单元格。使用此语法时,实际上会自动命名区域两端的行。如果网格区域的名称为foo,则该区域的起始行行和起始列行的名称为foo- start,其最后一行行和最后一列行的名称为foo -end。这意味着某些行可能具有多个名称,例如上例中的最左边的行,它将具有三个名称:header-start,main-start和footer-start。
grid-template(了解)
grid-template属性是grid-template-rows,grid-template-columns以及grid-template-areas的合并简写,该属性支持三种写法:
- none 将所有三个属性设置为其初始值。
.container {
grid-template: none;
}
- grid-template-rows / grid-template-columns 分别设置grid-template-columns和grid-template-rows为指定值,并设置grid-template-areas为none。
.container {
grid-template:
[row1-start] 25px [row1-end]
[row2-start] 25px [row2-end]
/ auto 50px auto;
}
/* 等价于 */
.container {
grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
}
- 设置 grid-template-rows,grid-template-columns以及grid-template-areas。
.container {
grid-template:
[row1-start] "header header header" 25px [row1-end]
[row2-start] "footer footer footer " 25px [row2-end]
/ auto 50px auto;
}
/* 等价于 */
.container {
grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
grid-template-areas:
"header header header"
"footer footer footer";
}
注意: 由于grid-template不重置隐式网格属性(grid-auto-columns,grid-auto-rows和grid-auto-flow),因此建议使用该grid属性代替grid-template。
column-gap (列间距)
row-gap (行间距)
grid-column-gap (列间距)
grid-row-gap (行间距)
通过上面的属性可以指定网格线的大小。即设置列/行之间的网格线的宽度。
注意:
grid-前缀将被删除,grid-column-gap并grid-row-gap重新命名为column-gap和row-gap。Chrome 68 +,Safari 11.2 Release 50+和Opera 54+已经支持无前缀属性。
gap网格线仅在列/行之间创建,而不在外边缘上创建。
.container {
/* 新标准 */
column-gap: <line-size>;
row-gap: <line-size>;
/* 旧写法 */
grid-column-gap: <line-size>;
grid-row-gap: <line-size>;
}
例:
.container {
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
column-gap: 10px;
row-gap: 15px;
}
gap间距简写
*grid-gap
gap 是 grid-gap 删除grid- 新标准写法,gap是row-gap和column-gap的简写,它更方便使用。
.container {
/* 新标准 */
gap: <row-gap> <column-gap>;
/* 旧写法 */
grid-gap: <grid-row-gap> <grid-column-gap>;
}
例:
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
gap: 15px 10px;
}
注意:gap属性可以只设置一个值表示将同样的值分别设置给row-gap和column-gap。
justify-items行轴:
在 CSS 网格中,每个网格项的内容分别位于被称为单元格(cell)的框内。你可以使用网格项的justify-self属性,设置其内容的位置在单元格内沿行轴(水平)对齐的方式。
.container {
justify-items: start | end | center | stretch;
}
-
start: 使内容在单元格左侧对齐
-
end: 使内容在单元格右侧对齐
-
center: 使内容在单元格居中对齐
-
stretch(默认值):内容占满整个单元格的宽度
也可以通过该justify-self属性在单个网格项目上设置此行为。
align-items列轴
与justify-items相反,对网格容器使用align-items属性可以给网格中所有的网格项设置沿列轴对齐的方式。
.container {
align-items: start | end | center | stretch;
}
-
start: 使内容在单元格上方对齐
-
end: 使内容在单元格下方对齐
-
center: 使内容在单元格垂直居中对齐
-
stretch:内容占满整个单元格的高度
也可以通过该align-self属性在单个网格项目上设置此行为。
place-items(行列轴简写)
place-items在单个声明中同时设置align-items和justify-items属性。
/*第一个值集align-items,第二个值justify-items。如果省略第二个值,则将第一个值分配给两个属性。*/
.container {
place-items: <align-items> <justify-items>
}
除Edge之外,所有主要浏览器均支持place-items属性。
justify-content网格对齐方式(行)
有时,网格的总大小可能小于其网格容器的大小。如果您所有网格项目的大小都设置为非弹性单位,则可能会发生这种情况。在这种情况下,您可以在网格容器中设置网格的对齐方式。该属性指定网格沿内嵌(行)轴对齐方式。
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
-
start: 网格沿容器左端对齐
-
end:网格沿容器右端对齐
-
center:网格沿容器水平居中对齐
-
stretch:调整网格项目的大小,填充满整个容器水平方向
-
space-around:每个网格项之间有相同的间隔, 网格项之间的间隔比网格与边框的间隔大一倍
-
space-between:边框两端对齐没有间隔,每个网格项目之间放置均匀的空间
-
space-evenly:在每个网格项目之间(包括边框两端)放置均匀的空间
align-content网格对齐方式(列)
与justify-contents属性网格沿内嵌(行)轴对齐相反,此属性使网格沿块(列)轴对齐。
.container {
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
-
start: 网格沿容器上端对齐
-
end:网格沿容器下端对齐
-
center:网格沿容器竖直居中对齐
-
stretch:调整网格项目的大小,填充满整个容器竖直方向
-
space-around:每个网格项上下之间有相同的间隔, 网格项之间的间隔比网格与上下边框的间隔大一倍
-
space-between:边框上下两端对齐没有间隔,每个网格项目上下之间放置均匀的空间
-
space-evenly:在每个网格项目之间(包括边框上下两端)放置均匀的空间
place-content(列行简写)
place-content在单个声明中同时设置 align-content 和 justify-content 属性。
/* 第一个值指定 align-content,第二个值指定justify-content。如果省略第二个值,则将第一个值分配给两个属性。*/
.container {
justify-content: <align-content> <justify-content>;
}
除Edge之外,所有主要浏览器均支持place-content属性。
grid-auto-columns
grid-auto-rows
指定任何自动生成的网格轨迹 (Grid Track) 也称为隐式网格轨轨迹的大小。
如果一个表格项目被定位在没有使用 grid-template-columns 显式指定尺寸的列中,隐式的 grid 轨道就会被创建出来支撑它。显式地定位到超出范围的列中,或者通过自动布局算法创建额外的列,就会发生上诉情况。
.container {
grid-auto-columns: <track-size> ;
grid-auto-rows: <track-size> ;
}
说明:
.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px;
}
当我们在网格容器中显式的制定了行与列尺寸时将创建一个2 x 2的网格。
假设您使用grid-column并按以下grid-row方式放置网格项并将网格项放入网格容器中:
grid-column,grid-row 我命会在网格项目属性中讲解,这里可以告诉大家他的大概意思就是给网各项设置定位指定所在的区域
.item-a {
grid-column: 1 / 2; /* 从网格线第1列开始 到第2列结束 */
grid-row: 2 / 3; /* 从网格线第2行开始 到第3列结束 */
}
.item-b {
grid-column: 5 / 6; /* 从网格线第5列开始 到第6列结束 */
grid-row: 2 / 3; /* 从网格线第2行开始 到第3列结束 */
}
上面的代码中 item-b元素引用了不存在的线(定位不在显式声明的网格轨迹中),因此将创建宽度为0的隐式轨迹以填充间隙。
grid-auto-columns和grid-auto-rows属性就可以指定这些隐式轨道的大小
.container {
grid-auto-columns: 60px;
}
grid-auto-flow
属性控制着自动布局算法怎样运作,精确指定在网格中被自动布局的元素怎样排列。
.container {
grid-auto-flow: row | column | row dense | column dense;
}
- row (默认):该关键字指定自动布局算法按照通过逐行填充来排列元素,在必要时增加新行。
- column :该关键字指定自动布局算法通过逐列填充来排列元素,在必要时增加新列。
- dense : 该关键字指定自动布局算法使用一种“稠密”堆积算法,如果后面出现了稍小的元素,尽早填充网格中的空白。这样做会填上稍大元素留下的空白,但同时也可能导致原来出现的次序被打乱,并可能导致它们显示混乱,这对可访问性不利。。
例子:
首先定义如下HTML结构
<section class="container">
<div class="item-a">item-a</div>
<div class="item-b">item-b</div>
<div class="item-c">item-c</div>
<div class="item-d">item-d</div>
<div class="item-e">item-e</div>
</section>
并定义一个具有五列两行的网格,并将其设置grid-auto-flow为row(这也是默认值):
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: row;
}
将项目放置在网格上时,只需为其中两个项定位:
.item-a {
grid-column: 1;
grid-row: 1 / 3;
}
.item-e {
grid-column: 5;
grid-row: 1 / 3;
}
因为设置grid-auto-flow为row,所以网格将如下所示。没有指定的三个项目(item-b,item-c和item-d)将会按照grid-auto-flow: row进行排列:
如果改为设置grid-auto-flow为column,则item-b,item-c和item-d沿列向下排列:
grid行列区域模板简写
可以用来设置以下属性:
- 显式网格属性 grid-template-rows、grid-template-columns 和 grid-template-areas,
- 隐式网格属性 grid-auto-rows、grid-auto-columns 和 grid-auto-flow,
注意:您仅可在一个 grid 属性中声明显式或隐式网格
.container {
grid: none | <'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>
}
- none : 将所有子属性设置为其初始值。
<grid-template>
: 与grid-template简写方式相同。
.container {
grid: 100px 300px / 3fr 1fr;
}
/*等价于*/
.container {
grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
}
.container {
grid: [row1-start] "header header header" 1fr [row1-end]
[row2-start] "footer footer footer" 25px [row2-end]
/ auto 50px auto;
}
.container {
grid-template-areas:
"header header header"
"footer footer footer";
grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
}
<grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>
?: 设置grid-template-rows为指定值。如果auto-flow关键字在斜杠的右侧,则将其设置grid-auto-flow为column。如果dense另外指定了关键字,则自动放置算法将使用“密集”打包算法。如果grid-auto-columns省略,则设置为auto。
.container {
grid: 100px 300px / auto-flow 200px;
}
.container {
grid-template-rows: 100px 300px;
grid-auto-flow: column;
grid-auto-columns: 200px;
}
[auto-flow && dense?] <grid-auto-rows>?/ <grid-template-columns>
置grid-template-columns为指定值。如果auto-flow关键字在斜杠的左侧,则将其设置grid-auto-flow为row。如果dense另外指定了关键字,则自动放置算法将使用“密集”打包算法。如果grid-auto-rows省略,则设置为auto。
.container {
grid: auto-flow dense 100px / 200px 1fr;
}
.container {
grid-auto-flow: row dense;
grid-auto-rows: 100px;
grid-template-columns: 1fr 2fr;
}
网格项目的属性
注意: float,display: inline-block,display: table-cell,vertical-align和column-*属性对网格项目没有影响。
grid-column-start
grid-column-end
grid-row-start
grid-row-end
通过上面四个属性可以确定网格的项目的位置,具体方法就是指定项目的四个边框,分别定位在哪根网格线。
.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;
}
<line>
: 可以是数字,用于引用已编号的网格线,也可以是名称,用于引用已命名的网格线- span
<number>
:span关键字,表示"跨越",即项目将跨越提供的网格轨迹数量 - span
<name>
: 项目将跨过,直到命中提供名称的那一行 - auto: 表示自动放置,自动跨度或默认跨度为1
例一:
.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-end/ grid-row-end,则默认情况下该项将跨越1条轨道。
grid-column
grid-row
grid-column属性是grid-column-start和grid-column-end的合并简写形式,
grid-row属性是grid-row-start属性和grid-row-end的合并简写形式
.item {
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的简写。
.item {
grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
例:
.item-d {
grid-area: header;
}
.item-d {
grid-area: 1 / col4-start / last-line / 6;
}
justify-self
属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目。
.item {
justify-self: start | end | center | stretch;
}
- start: 对齐单元格的起始边缘
- end: 对齐单元格的结束边缘
- center: 沿单元格水平位置居中。
- stretch(默认): 拉伸,占满单元格的整个宽度
align-self
属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,也是只作用于单个项目。
.item {
align-self: start | end | center | stretch;
}
- start: 对齐单元格的起始边缘
- end: 对齐单元格的结束边缘
- center: 沿单元格水平位置居中。
- stretch: 拉伸,占满单元格的整个宽度
place-self
属性是align-self属性和justify-self属性的合并简写形式。
.item {
place-self: auto | <align-self> / <justify-self>
}
- auto: 布局模式的“默认”对齐方式
<align-self> / <justify-self>
: 第一个值集align-self,第二个值justify-self。如果省略第二个值,则将第一个值分配给两个属性。
注意:除Edge之外,所有主要浏览器均支持place-selfshorthand属性。
特殊功能和关键字
使用 repeat 函数减少重复:
介绍:当使用grid-template-columns和grid-template-rows定义网格结构时,你需要为添加的每一行和每一列都输入一个值。
如果要添加带 100 行高度相同的网格,单独放入 100 个值不太实际。
语法: repeat(指定行或列的重复次数, 需要重复的值)。
/* 添加 100 行网格,使每行高度均为 50px */
.container {
grid-template-rows: repeat(100, 50px);
}
/* 添加 3列网格,使每行宽度均为 20px 并设置网格线名为 col-start */
.container {
grid-template-columns: repeat(3, 20px [col-start]);
}
/* repeat 方法重复多重值 */
.container {
grid-template-columns: repeat(2, 1fr 50px) 20px; /*等价于 1fr 50px 1fr 50px 20px; */
}
使用 minmax 函数限制项目大小
介绍:内置函数minmax也可以可用于设置grid-template-columns和grid-template-rows的值。它的作用是在网格容器改变大小时限制网格项的大小。指定网格项允许的尺寸范围。
语法:minmax(指定最小值, 指定最大值)。
/* grid-template-columns被设置为添加两列,第一列 100px 宽,第二列宽度最小值是 50px,最大值是 200px */
.container {
grid-template-columns: 100px minmax(50px, 200px);
}
使用 auto-fill 创建弹性布局
介绍:重复方法带有一个名为自动填充(auto-fill)的功能。它的功能是根据容器的大小,尽可能多地放入指定大小的行或列。你可以通过结合auto-fill和minmax来更灵活地布局。
/* 列的宽度会随容器大小改变,在可以插入一个 60px 宽的列之前,当前行的所有列会一直拉伸 */
.container {
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
}
注意:如果容器无法使所有网格项放在同一行,余下的网格项将移至新的一行。
使用 auto-fit 创建弹性布局
介绍:auto-fit效果几乎和auto-fill一样。不同点仅在于,当容器的大小大于各网格项之和时,auto-fill将会持续地在一端放入空行或空列,这样就会使所有网格项挤到另一边;而auto-fit则不会在一端放入空行或空列,而是会将所有网格项拉伸至合适的大小。
/* 列的宽度会随容器大小改变,当前行的所有列会一直拉伸 */
.container {
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
}
注意: 如果容器无法使所有网格项放在同一行,余下的网格项将移至新的一行。
columns被设置为添加两列,第一列 100px 宽,第二列宽度最小值是 50px,最大值是 200px */
.container {
grid-template-columns: 100px minmax(50px, 200px);
}
### **使用 auto-fill 创建弹性布局**
**介绍**:重复方法带有一个名为自动填充(auto-fill)的功能。它的功能是根据容器的大小,尽可能多地放入指定大小的行或列。你可以通过结合auto-fill和minmax来更灵活地布局。
```css
/* 列的宽度会随容器大小改变,在可以插入一个 60px 宽的列之前,当前行的所有列会一直拉伸 */
.container {
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
}
注意:如果容器无法使所有网格项放在同一行,余下的网格项将移至新的一行。
使用 auto-fit 创建弹性布局
介绍:auto-fit效果几乎和auto-fill一样。不同点仅在于,当容器的大小大于各网格项之和时,auto-fill将会持续地在一端放入空行或空列,这样就会使所有网格项挤到另一边;而auto-fit则不会在一端放入空行或空列,而是会将所有网格项拉伸至合适的大小。
/* 列的宽度会随容器大小改变,当前行的所有列会一直拉伸 */
.container {
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
}
注意: 如果容器无法使所有网格项放在同一行,余下的网格项将移至新的一行。