Grid —— CSS网格布局初探
前言
CSS网格布局是CSS中最强大的布局系统。 这是一个二维系统,这意味着它可以同时处理列和行, 不像flexbox那样主要是一维系统。 你可以通过将CSS规则应用于父元素(网格容器) 和该元素的子元素(网格元素)来使用网格布局。
通过网格布局和媒体查询的结合,不需要修改任何文档结构就可以重新排列元素布局的顺序,达到理想的布局效果。
下文中可点击”点击展开“查看具体代码及效果,可以点击“show in codepen”跳转到codepen自行调试,如没有,请点击原文链接查看原文。
先看一个例子: 这种布局已经司空见惯了。我们看用grid的话,可以有哪些骚操作:
<div class="grid">
<div class="item header">header</div>
<div class="item content">content</div>
<div class="item sidebar">sidebar</div>
<div class="item footer">footer</div>
</div>
2
3
4
5
6
.grid {
display: grid;
grid-gap: 5px;
height: 400px;
grid-template-areas: "header header"
"content sidebar"
"footer footer";
grid-template-columns: 1fr 100px;
grid-template-rows: 80px 1fr 80px;
}
.header {
grid-area: header;
background-color: #009688;
}
.content {
grid-area: content
}
.sidebar {
grid-area: sidebar;
background-color: #ff5722;
}
.footer {
grid-area: footer;
background: #9c27b0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
几个概念
网格容器(Grid Container)
顾名思义,真个望各位布局的容器,所有网格项目的父元素,例如上面例子中.grid。
网格项目(Grid Item)
网格容器里的子元素(直接子元素),上例中的.item。
网格线(Grid Line)
简单理解,就是网格元素之间的缝隙。它们既可以是垂直的,也可以是水平的,并位于行或列的任一侧。
网格轨道(Grid Track)
两个相邻网格线之间的空间。 可以把它们想象成网格的列或行。
网格单元(Grid Cell)
两个相邻的行和两个相邻的列网格线之间的空间。它是网格的一个“单元”。
网格区域(Grid Area)
四个网格线包围的总空间。 网格区域可以由任意数量的网格单元组成。
属性列表
网格容器
- display
- grid
- grid-template
- grid-template-columns
- grid-template-rows
- grid-template-areas
- grid-gap(grid-column-gap/grid-row-gap)
- grid-auto-flow
- grid-auto-columns
- grid-auto-rows
- justify-items
- align-items
- justify-content
- align-content
网格项目
- grid-column(grid-column-start/grid-column-end)
- grid-row(grid-row-start/grid-row-end)
- grid-area
- justify-self
- align-self
下面我们一起详细地学习这些属性——
display
.grid {
display: grid | inline-grid | subgrid;
}
2
3
- grid – 生成一个块级(block-level)网格
- inline-grid – 生成一个行级(inline-level)网格
- subgrid – 如果你的 grid container 本身就是一个 grid item(即,嵌套网格),你可以使用这个属性来表示你想从它的父节点获取它的行/列的大小,而不是指定它自己的大小。
grid-template-columns / grid-template-rows
.grid {
grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}
2
3
4
用空格分隔的值来定义网格的列和行,值表示的是轨道大小。 如果轨道值之间有line name,表示自定义的网格线名称,如果没有,系统会自动分配从1开始递增的数字名称。
轨道值
任何非负值,长度可以是px、%、em等长度单位的值。 如:
grid-template-columns: 100px 30% 200px;
grid-template-rows: 50px 100px;
2
定义了一个2行3列的网格,第二列占据30%父元素宽度。
grid-template-columns: 100px 2fr 1fr;
grid-template-rows: 50px 100px;
2
fr单位可以创建一个弹性的网格轨道。这个例子中,网格容器的列分成了100px和3等份(1 + 2 = 3),每一份(1fr)是网格容器宽度的三分之一。所以第二个item和第三个item的宽度分别是网格容器宽度的三分之二和三分之一。
如果定义中包含重复的部分,则可以使用repeat()方法来简化写法:
grid-template-columns: repeat(2, 100px 1fr);
参数1是可以是重复的次数,参数2是重复的内容。
参数1也可以是auto-fill和auto-fit。
auto-fill创建了许多与网格容器相匹配的轨道,而不会导致网格溢出。
auto-fit与auto-fill类似,只是在网格项放置之后,它只会在需要时创建尽可能多的轨道,而重复的空轨道会堆叠在一起(合并)。
对于同样的四个项目的结构,二者的区别见下图:
grid-template-columns: repeat(auto-fill, 100px);效果着这样婶儿的:
grid-template-columns: repeat(auto-fill, 100px);效果是这样婶儿的:
具体有什么用?😰 额。。。我也不太清楚,这里先不深究了。
minmax
grid-template-columns/rows的参数还可以使用minmax函数,具体怎么使用可以看这里minmax()函数如何工作
grid-gap
.grid {
grid-gap: <grid-row-gap> <grid-column-gap>;
}
2
3
这个简单,是grid-column-gap和grid-row-gap的缩写形式,分别定义列与列、行与行之间的间隙。上面的例子已经用到了。
grid-column / grid-row
grid-column:grid-column-start / grid-column-end的缩写
grid-row:grid-row-start / grid-row-end的缩写
可使用grid-column / grid-row来定义网格的大小(跨度)定位网格。定位我们一会再说,先看下如何定义网格的大小。 这类似于table的合并单元格(rowspan、colspan),不同的是网格项数目并不会增减。
grid-column: span 2;
grid-row: span 2;
2
通过网格线名称定位
grid-column: 2 / 4;
grid-row: 3 / 5;
2
相当于
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 3;
grid-row-end: 5;
2
3
4
也相当于
grid-column: 2 / 4;
grid-row: 3 / 5;
2
而
grid-column: 2;
grid-row: 3;
2
相当于
grid-column-start: 2;
grid-column-end: auto;
grid-row-start: 3;
grid-row-end: auto;
2
3
4
grid-column: 2 / span 2;
grid-row: 3 / span 2;
2
通过网格区域定位
grid-area
grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end的缩写,可以是默认的数字网格线名称,也可以是自定义的网格线名称,
还可以是一个具体的自定义的名称,见开头的例子: 给每个块定义grid-area名称,然后通过grid-template-areas定义块的布局。这种写法简单明了,一眼就能看出整体布局。
隐式网格(Implicit Grid)
想象一下:网格容器中,我们定义了一个3行4列的网格,但是容器的直接子元素多余3×4=12个,那个多余的子元素该怎么安排呢。 css规定,没有显式地定义的网格项目(即显式网格外面的项目)会形成一个隐式网格。这一部分元素可通过grid-auto-columns、 grid-auto-rows和grid-auto-flow控制。
grid-auto-columns / grid-auto-rows
分别定义隐式网格列和行的尺寸。
grid-auto-flow
默认值是row,定义网格的展示方式:网格项目是按列的方式还是行的方式排列。
.grid {
grid-auto-flow: row | column | row dense | column dense
}
2
3
tip
可以给grid-auto-flow属性添加另外一个关键词dense(密集的),这个属性值相当有用:系统会利用自动排列算法尽可能的填补空缺, 使布局变得密集。但这可能打乱元素原来的顺序,这也意味着它不能友好地反映文档流顺序,这一点对于一些用户而言并不总是有用的。
看下前后对比图:
前:
后:
对齐相关
justify-items、justify-self指定网格项目沿着行轴对齐方式。
align-items、align-self指定网格项目沿着列轴对齐方式。
align-content指定网格轨道沿着行轴对齐方式; justify-content指定网格轨道沿着列轴对齐方式。
他们所对应的值及具体表现形式,可参考这里,不再赘述了。
浏览器调试
firefox里,可以通过设置显示网格的名称、行号等信息,点这里看详情,非常方便, 如下图:
tip
从图中可以看出,grid-column/row-start/end是可以为负数的,正负值差别是,位置将从相反的方向开始。
这样看来*-end也是可以小于*-start的。
chrome的高一点版本(我的是67),可以显示对应网格线,不知道能不能进一步设置?。。。 如下图: 但是chrome有一个网格布局高亮插件可以帮助到我们。
总结
关于Grid布局,本文讲解的东西对于全民啊理解网格布局还只是杯水车薪,其中的好多细节都没有涉及到。 若发现有错误的地方,欢迎不吝指教!🙏