这是HTML&CSS重点知识点合集第四篇,内容稍微有点多。其他文章见文末。css
前面咱们讲了 伸缩盒。咱们讲到,伸缩盒是传统盒模型布局的一种代替,而且伸缩容器以及flex item的属性足以应付咱们经常使用的各类布局模式,那为何还会出现Grid网格布局呢?html
可能你已经知道了,以往任何布局方式几乎都是一维布局,而Grid最大的特点就是采用了二维布局。固然,Grid的出现并非用来替代flex-layout,而是对它的补充。前者擅长一维然后者擅长二维,它们须要各司其职。前端
咱们来看看它的兼容性吧。从2017年3月份开始,Grid开始获得部分的浏览器的支持。css3
你可能会有疑问,Grid不就是设置行和列嘛?但是这些table不是均可以作嘛?那为啥还要有Grid?git
从效果上来看,Grid布局和table同样都是把一部分区域经过行和列来划分红一小块一小块方格。可是实际上它们是有很大区别的: 1.首先,它们的本质区别在于Grid是用纯CSS实现的布局方式。而table布局依赖HTML标签,它有固定的结构。Grid能够直接使用 grid-template-columns
和 grid-template-rows
属性来设置容器的行和列的长度。例如:github
.container {
display: grid;
grid-template-columns: 50px 50px 50px;
grid-template-rows: 50px 50px 50px;
}
复制代码
当咱们对一个容器设置上述样式,就会生成一个三行三列且每一小格长宽均为50px。点击这里 本身实践一下!浏览器
2.其次,基于table固定标签的结构,它的布局就很不自由。可是Grid不一样,使用它来对二维布局能够利用几行代码轻松实现,灵活性很高。网络
在具体讲Grid布局以前,咱们先来认识几个术语。ide
第1、和伸缩盒同样,网格布局中也有容器这个概念。网格容器(Grid container),为其内容创建新的网格格式化上下文,容器外元素和容器内元素互不干扰。好比上图中盛装数字块的最外容器。函数
第2、网格线(Grid line),顾名思义,容器的水平垂直分割线。它构建出网格轨道、网格单元和网格区域。网格线是有数字索引的,能够自定义名称。
第3、网格轨道(Grid track),网格内容块之间水平或垂直的空间。
第4、网格单元格(Grid cell),网格内容的单元区块,是能够放置内容的最小区块。好比上图中的某一个数字块。
第5、网格区域(Grid area),以网格线为界划定区域。
网格容器全部的属性:
display
grid-template-columns
grid-template-rows
grid-template-areas
grid-template
grid-column-gap
grid-row-gap
grid-gap
justify-items
align-items
place-items
justify-content
align-content
place-content
grid-auto-columns
grid-auto-rows
grid-auto-flow
grid
和伸缩盒不同,在网格布局是一个二维布局,有着行和列的概念,因此咱们接下来说的容器属性是:如何定义网格容器以及如何定义网格的行数、列数以及网格的大小(长宽)。
1. display
.container {
display: grid | inline-grid;
}
复制代码
2. grid-template-columns
和 grid-template-rows
就如上面例子中同样,它们用来定义网格的行数、列数、网格大小。假设咱们须要定义一个四行四列的容器能够这样写:grid-template-columns: 50px 50px 50px 50px; grid-template-rows: 50px 50px 50px 50px;
。
固然,属性值除了可使用 px
做为单位还可使用 em
、%
来做为单位。在CSS3规范中,咱们看到这样一段话:
A flexible length or is a dimension with the fr unit, which represents a fraction of the leftover space in the grid container. Tracks sized with fr units are called flexible tracks as they flex in response to leftover space similar to how flex items fill space in a flex container.
翻译过来就是说 fr
这个单位表示的是网格容器中剩余空间的一部分。大小为 fr
单位的‘轨道’称为弹性‘轨道’,它们会响应式的填充剩余的内容,和伸缩盒中的flex item会自动填充剩余空间很类似。
假设设置一个三行四列的列表,但愿最后一列自适应容器宽度就能够这样设置:
.container {
display: grid;
grid-template-columns: 50px 50px 50px 1fr;
grid-template-rows: 50px 50px 50px;
}
复制代码
那若是但愿第一列长度固定然后三列中第一列占剩余长度的四分之一,第二列占二分之一最后一列占四分之一应该该怎么写呢?
.container {
display: grid;
grid-template-columns: 50px 1fr 2fr 1fr;
grid-template-rows: 50px 50px 50px;
}
复制代码
怎么样?神奇吧?
对于这两个属性,CSS3还提供了一个函数:repeat()
。它的做用相信你一看就知道了:
.container {
display: grid;
grid-template-columns: 50px 1fr 2fr 1fr;
grid-template-rows: repeat(3, 50px);
}
复制代码
3. grid-template-areas
.container {
grid-template-areas: "<grid-area-name> | . | none | ..." "...";
}
复制代码
它用来定义网格区域,使用 grid-area
调用声明好的网格区域名称用来放置对应的网格项目。
举个栗子:
.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;
grid-template-areas:
"header header header header"
"main main . sidebar"
"footer footer footer footer";
}
复制代码
咱们经过Grid item的属性 grid-area
(后面会讲到)来为item设置相应的名称,而后再利用容器属性 grid-template-areas
经过设置的名称对整个容器布局。下面就是布局的效果:
4. grid-template
这是属性 grid-template-rows
,grid-template-columns
和 grid-template-areas
三个属性的简写。
.container {
grid-template: none | <grid-template-rows> / <grid-template-columns>;
}
复制代码
当仅仅设置 grid-template-rows
,grid-template-columns
时,grid-template-areas
自动为 none
。中间使用符号 /
隔开。好比前面一个例子就能够写成这样:
.container {
display: grid;
grid-template: repeat(3, 50px) / 50px 1fr 2fr 1fr;
}
复制代码
grid-template
不会隐式的设置 grid-auto-columns
、grid-auto-rows
和 grid-auto-flow
,因此推荐使用 grid
属性来代替。
5. grid-row-gap
和 grid-column-gap
定义网格之间的间距(不包括grid item到容器边缘的间距)
6. justify-items
.container {
justify-items: start | end | center | stretch; /* 默认值为stretch */
}
复制代码
定义Grid item的内容在水平方向上的对齐方式(其值指的是在单元格内的表现)。好比:
.container {
justify-items: start;
}
复制代码
.container {
justify-items: center;
}
复制代码
和伸缩容器的 align-items
同样,它也能在子项目中使用属性 justify-self
进行覆盖。
7. align-items
.container {
align-items: start | end | center | stretch;
}
复制代码
和 justify-items
差很少,只不过这个属性做用的是另外一个轴方向。
.container {
align-items: start;
}
复制代码
一样的,这个属性值也能够利用子项目的属性 align-self
进行覆盖。
8. place-items
是属性 align-items
和属性 justify-items
的简写。中间使用 /
进行分隔。若只有一个值,那么将同时设置两个相同的值。
注:除了Edge,全部主流浏览器均支持该属性。
9. justify-content
有些时候,当咱们对单元格的长设置了固定值,这时就有可能致使全部网格的长加起来不能撑满整个网格容器。好比下面这样:
因此,justify-content
属性就运用而生。它主要就是设置容器中内容的排布方式的。
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
复制代码
栗子以下:
.container {
justify-content: space-around;
}
复制代码
10. align-content
和上一个属性相呼应,若是咱们对每一个单元格的高设置固定值,这是就有可能致使全部单元格的高加起来没有填满整个容器。
.container {
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
复制代码
11. place-content
前两个属性的简写形式,若是只设置一个值,则表示设置相同的值。
除Edge外,全部主流浏览器都支持这个属性。
12. grid-auto-columns
、grid-auto-rows
设置隐式网格轨道的大小。
.container {
grid-auto-columns: <track-size> ...;
grid-auto-rows: <track-size> ...;
/* <track-size> 长度,能够是前面提到的任何表示形式 */
}
复制代码
其实这个属性就是设置以后有可能动态添加进来的item的长度和高度。来看下面一个栗子: 首先,咱们设置好高宽:
.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px;
}
复制代码
如今咱们来对Grid item设置一下它的位置(这两个属性接下来会讲到,用来设置item的位置,其中/
两侧的值分别是网格轨道的起始位置和终点位置):
.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.item-b {
grid-column: 5 / 6;
grid-row: 2 / 3;
}
复制代码
在这里咱们设置了一个 item-b
,而且容易看出,它在原先定义的网格中并不存在,因而就有了上图。看到,第3、四列的长度为0,且 item-b
的这一列的长度也为没设置(默认值为 auto
,和前面已经定义的长度同样)。
如何解决第3、四列的长度问题呢?这里咱们就能够利用属性 grid-auto-columns
来动态的设置后添加进来item的长度。
.container {
grid-auto-columns: 60px;
}
复制代码
13. grid-auto-flow
.container {
grid-auto-flow: row | column | row dense | column dense;
}
复制代码
它定义了默认“流”方向,它的动做和flexbox里的 flex-direction
有些类似。
14. grid
它是属性 grid-template-rows
、grid-template-columns
、grid-template-areas
、grid-auto-rows
、grid-auto-columns
以及grid-auto-flow
的缩写。
.container {
grid: none | <grid-template> | <grid-template-rows> / [auto-flow && dense?] <grid-auto-columns>? | [auto-flow && dense?] <grid-auto-rows>? / <grid-template-columns>;
}
复制代码
举个栗子就明白啦:
.container {
grid: 100px 300px / 3fr 1fr;
}
/* 等同于下面: */
.container {
grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
}
复制代码
再好比:
.container {
grid: auto-flow / 200px 1fr;
}
/* 等同于下面: */
.container {
grid-auto-flow: row;
grid-template-columns: 200px 1fr;
}
.container {
grid: auto-flow dense 100px / 1fr 2fr;
}
/* 等同于 */
.container {
grid-auto-flow: row dense;
grid-auto-rows: 100px;
grid-template-columns: 1fr 2fr;
}
复制代码
全部Grid item属性:
grid-column-start
grid-column-end
grid-row-start
grid-row-end
grid-column
grid-row
grid-area
justify-self
align-self
place-self
1. grid-column-start
、grid-column-end
、grid-row-start
、grid-row-end
这四个属性是用来定义item的四周位置的。
.item {
grid-column-start: <line> | <number> | <name> | span <number> | span <name> | auto;
grid-column-end: <line> | <number> | <name> | span <number> | span <name> | auto;
grid-row-start: <line> | <number> | <name> | span <number> | span <name> | auto;
grid-row-end: <line> | <number> | <name> | span <number> | span <name> | auto;
}
复制代码
其中 <line>
的值能够是一个数字,表示第几根网格线,也能够是已经定义过的网格线名称。
举个栗子:
.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 item有时候可能会相互重叠,这时候可使用 z-index
控制其层叠顺序。
2. grid-column
、grid-row
前者是属性 grid-column-start
和 grid-column-end
的简写,后者是属性 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;
}
复制代码
3. grid-area
这个属性咱们前面提到过,它能够用来定义Grid item的名称,用来给属性 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>;
}
复制代码
关于 <name>
的栗子上面已经有了,这里再也不赘述。下面举第二个值得栗子:
.item-d {
grid-area: 1 / col4-start / last-line / 6;
}
复制代码
4. justify-self
、align-self
前面也提到啦,这两个属性都是子元素对父元素设置的 justify-items
和 align-items
进行覆盖。这里就再也不举栗子惹~
5. place-self
这个属性仍是比较厉(sao)害(qi)的~ 看用法:
.item-a {
place-self: auto | <align-self> / <justify-self>;
}
复制代码
栗子:
.item-a {
place-self: center;
}
复制代码
.item-a {
place-self: center stretch;
}
复制代码
最后,Grid item对属性 float
、display: inline-block
、display: table-cell
、vertical-align
、column-*
失效。
px
、res 、%,这些咱们以往使用的单位。咱们还可使用关键字:min-content
、max-content
、auto
,固然,可能最有用的仍是 fr
。minmax()
来设置一个大小的区间段。repeat()
,前面已经有讲过,这里再也不赘述。根据CSS网格布局模型Level 1,有5个网格动画属性,分别是: grid-gap
、grid-row-gap
、grid-column-gap
、grid-template-columns
、grid-template-rows
。
我看能够利用 @keyframes
规则,经过改变这五个属性大小达到想要的动画效果。
这里有个使用属性 transition
来实现动画的栗子:动画demo
justify-items
而伸缩容器没有属性 justify-items
?首先,咱们来对比一下伸缩容器的 justify-content
和网格容器的 justify-content
:
容易看出,在伸缩容器中,每个item都是一个排列单元,而在网格容器中,每一列是一个排列单元。
如今咱们再来看看网格容器的属性:justify-items
。
它的做用是在水平方向设置item内容的对齐方式。若是设置为 start
,则表示全部item的内容靠近左网格线。若是设置为 center
,则表示将内容在水平方向居中显示。在网格这个二维空间中,显然它是很是有用的属性。而若是咱们也为伸缩布局设置这个属性,很显然和它的属性 justify-content
的做用发生的重叠,且效果没有前者好。所以,在伸缩容器中定义 justify-items
是没有必要的。
当咱们有大量的内容绘制到页面上、或者内容更改的,在2g或者网络加载不稳定的时候,页面是不稳定的。网格布局会以流的形式被获取到,且能使咱们在页面所有加载出来以前就看到内容,而flex布局因为其相对布局的特征会致使布局的重排。
固然并非说网格布局就必定不会引起重排,它是有前提的:网格的划分是预先肯定的,好比根据视窗高度来肯定。
假如内容是根据内容弹性改变的,那么也没法避免发生重排。
ps: 最后的最后,终于整理完啦,满满的收获呀。固然啦,但愿你能有所收获~
这里给你们推荐一个有趣的Grid游戏吧:grid garden,还蛮有意思的,用来入门简直不要太好~
这是HTML&CSS重点知识点合集的其中一篇,合集其它文章:
1.语义化HTML的重要性
2.传说中的BFC
3.CSS布局神器——伸缩盒(语法篇)
参考文章:
1.将来布局之星Grid-2017-09-24 by 考拉海购前端团队
2.CSS Grid 网格布局教程-2019-03-25 by 阮一峰
推荐阅读: 1.A Complete Gide to Grid-2019-9-13 by Chris
有问题?发送 issues 给我~