学习CSS Grid
CSS Grid是一个强大的工具,它允许在Web上创建二维布局。这一篇学习CSS Grid的指南,通过图形的方式帮助您更好的理解和学习CSS Grid。花时间整理和阅读这篇文章都是非常有意义的。
我们要特别感谢Mozilla开发人员和W3C规范中有关于CSS Grid的资源。同时也需要特别感谢@Jen Simmons和@Rachel Andrews两位女士,她们是CSS Grid的主要贡献者,可以说要是没有她们,就没有今天的CSS Grid。
网格容器
通过display
属性设置属性值为grid
或inline-grid
可以创建一个网格容器。网格容器中的所有子元素就会自动变成网格项目(grid item)。
display: grid
网格项目默认放在行中,并且跨网格容器的全宽。
display: inline-grid
显式网格
使用grid-template-columns
和grid-template-rows
属性可以显式的设置一个网格的列和行。
grid-template-rows: 50px 100px
grid-template-rows
指定的每个值可以创建每行的高度。行高的尺寸可以是任何非负值,长度可以是px
、%
、em
等长度单位的值。
item1
和item2
具有固定的高,分别为50px
和100px
。
因为只定义了两个行的高度值,所以item3
和item4
的高度是根据其自身的内容来定义。
grid-template-columns: 90px 50px 120px
像行一样,通过grid-template-columns
指定的每个值来创建每列的列宽。
item4
、item5
和item6
放置在新的一行(第二行),因为grid-template-columns
只定义了三列的大小,它们也分别放置在列1、列2和列3;其中列1、列2和列3的尺寸大小等于item1
、item2
和item3
宽度。
item1
、item2
和item3
具有固定的宽度值,分别为90px
、50px
和120px
。
grid-template-columns: 1fr 1fr 2fr
fr
单位可以帮助我们创建一个弹列的网格轨道。它代表了网格容器中可用的空间(就像Flexbox中无单位的值)。
在这个示例中,网格容器分成了4
等份(1 + 1 + 2 = 4
),每一份(1fr
)是网格容器宽度的四分之一。所以item1
和item2
的宽度是网格容器的四分之一宽,item3
是网格容器宽度的四分之二(2fr
)。
grid-template-columns: 3rem 25% 1fr 2fr
当fr
和其它长度单位的值结合在一起的时候,fr
是基于网格容器可用空间来计算。
在这个示例中,网格容器可用空间是网格宽度减去3rem
和25%
剩下的宽度,而fr
就是基于这个尺寸计算:
1fr = (网格宽度 - 3rem - 网格宽度 * 25%) / 3
网格轨道最小和最大尺寸
可以通过minmax()
函数来创建网格轨道的最小或最大尺寸。
grid-template-rows: minmax(100px, auto);
grid-template-columns: minmax(auto, 50%) 1fr 3em;
minmax()
函数接受两个参数:第一个参数定义网格轨道的最小值,第二个参数定义网格轨道的最大值。可以接受任何长度值,也接受auto
值。auto
值允许网格轨道基于内容的尺寸拉伸或挤压。
在这个示例中,第一行的高度最小值是100px
,但其最大值为auto
,允许行高可以变大超过100px
。
第一列设置了最小值为auto
,但它的最大值是50%
,也就是列的最大宽度不会超过网格容器宽度的50%
。
重复网格轨道
使用repeat()
可以创建重复的网格轨道。这个适用于创建相等尺寸的网格项目和多个网格项目。
grid-template-rows: repeat(4, 100px);
grid-template-columns: repeat(3, 1fr);
repeat()
也接受两个参数:第一个参数定义网格轨道应该重复的次数,第二个参数定义每个轨道的尺寸。
grid-template-columns: 30px repeat(3, 1fr) 30px
repeat()
也可以用在轨道列表中。
在这个示例中,第一列和最后一列的宽度都是30px
,并且它们之间有另列三列,这三列是通过repeat()
来创建的,而且每列的列宽是1fr
(1fr = (网格宽度 - 30px - 30px) / 3
)。
间距
grid-column-gap
和grid-row-gap
属性用来创建列与列,行与行之间的间距。
grid-gap
只能创建列与列或行与行之间的间距,但不能创建列和行与网格容器边缘的间距。
grid-row-gap: 20px;
grid-column-gap: 5rem;
间距(Gap)可以设置任何非负值,长度值可以是px
、%
、em
等单位值。
grid-gap: 100px 1em;
grid-gap
是grid-row-gap
和grid-column-gap
两个属性的缩写。
如果它指定了两个值,那么第一个值是设置grid-row-gap
的值,第二个值设置grid-column-gap
的值。
grid-gap: 2rem;
如果只设置了一个值,表示行和列的间距相等,也就是说grid-row-gap
和grid-column-gap
的值都相同。
通过网格线号码来定位网格项目
网格线实际上是代表线的开始、结束,两者之间就是网格列或行。
每条线是从网格轨道开始,网格的网格线从1
开始,每条网格线逐步增加1
。
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 2;
grid-column-end: 3;
两列三行的网格创建三条列网格线和四条行网格线。item1
就是由行和列的号码重新定位。
如果一个网格项目跨度只有一行或一列,那么grid-row-end
和grid-column-end
不是必需的。
grid-row: 2;
grid-column: 3 / 4;
grid-row
是grid-row-start
和grid-row-end
的简写。grid-column
是grid-column-start
和grid-column-end
的简写。
如果只提供一个值,他指定了grid-row-start
和grid-column-start
的值。
如果提供两个值,第一个值是grid-row-start
、grid-column-start
的值,第二个值是grid-row-end
、grid-column-end
的值,两者之间必须要用/
隔开。
grid-area: 2 / 2 / 3 / 3;
如果指定四个值,第一个值对应grid-row-start
,第二个值对应grid-column-start
,第三个值对应grid-row-end
和第四个值对应grid-column-end
。
网格项目跨行或跨列
默认情况下网格项目跨度只有一个列和行,但可以跨越多个行和列。
grid-column-start: 1;
grid-column-end: 4;
可以通过设置grid-column-end
和grid-column-start
距离多个网络线号实现多个列跨越。
grid-row-start: 1;
grid-row-end: 4;
同样的可以通过grid-row-end
和grid-row-start
距离多个网格号实现多个行跨越。
grid-row: 2 / 5;
grid-column: 2 / 4;
通过简写的grid-row
和grid-column
也能实现多行或多列的跨越。
grid-row: 2 / span 3;
grid-column: span 2;
关键词span
后面紧随数字,表示合并多少个列或行。
网格线命名
通过grid-template-rows
和grid-template-columns
定义网格时,网格线可以被命名。网格线名称也可以设置网格项目位置。
grid-template-rows: [row-1-start] 1fr [row-2-start] 1fr [row-2-end];
grid-template-columns: [col-1-start] 1fr [col-2-start] 1fr [col-3-start] 1fr [col-3-end];
grid-template-rows
和grid-template-columns
定义你的网格,将名称分配给网格线。
定义网格线名称时需要避免使用规范中出现的关键词,以免导致混乱。
分配网格线名称必须用方括号[网格线名称]
,然后后面紧跟网格轨道的尺寸值。
grid-template-rows: [row-start row-1-start] 1fr [row-1-end row-2-start] 1fr [row-2-end row-end];
grid-template-columns: [col-start] 1fr [col-2-start] 1fr [col-3-start] 1fr [col-end];
可以在方括号中添加多个名称来命名网格线名称,使用多外名称命名网格线名称时,名称间要用空格隔开。
每一个网格线的名称可以用来定位网格项目的位置。
通过网格线名称设置网格项目位置
使用网格线名称设置网格项目位置和使用网格线号码设置网格项目位置类似。
grid-row-start: row-2-start;
grid-row-end: row-end;
grid-column-start: col-2-start;
grid-column-end: col-end;
引用网格线名称的时候不应该带方括号。
grid-row: row-2-start / row-end;
grid-column: col-2-start / col-end;
grid-row
和grid-column
简写属性也适用于网格线名称,也可以用来设置网格项目的位置。
使用相同的名称命名网格线和设置网格项目位置
使用repeat()
函数可以给网格线分配相同的名称。这可以节省一定的时间。
grid-template-rows: repeat(3, [row-start] 1fr [row-end]);
grid-template-columns: repeat(3, [col-start] 1fr [col-end]);
使用repeat()
函数可以给网格线命名,这也导致多个网格线具有相同的网格线名称。
相同网格线名称指定网格线的位置和名称,也且会自动在网格线名称后面添加对应的数字,使其网格线名称也是唯一的标识符。
grid-row: row-start 2 / row-end 3;
grid-column: col-start / col-start 3;
使用相同的网格线名称可以设置网格项目的位置。网格线的名称和数字之间需要用空格分开。
在这个示例中,item1
放置位置是row-start
第2
条开始,至row-end
的第3
条结束,这用来设置item1
在行的起始和结束位置;col-start
的第1
条开始,至col-start
的第3
条结束(col-start
的第3
条也对应的是col-end
的第2
条),用来设置item1
在列的起始位置和结束位置。
通过网格区域命名和定位网格项目
像网格线名称一样,网格区域的名称也可以使用grid-template-areas
属性来命名。引用网格区域名称也可以设置网格项目位置。
grid-template-areas: "header header"
"content sidebar"
"footer footer";
grid-template-rows: 150px 1fr 100px;
grid-template-columns: 1fr 200px;
设置网格区域的名称应该放置在单引号或双引号内,每个名称由一个空格符分开。
网格区域的名称,每组(单引号或双引号内的网格区域名称)定义了网格的一行,每个网格区域名称定义网格的一列。
grid-row-start: header;
grid-row-end: header;
grid-column-start: header;
grid-column-end: header;
grid-row-start
、grid-row-end
、grid-column-start
和grid-column-end
可以引用网格区域名称,用来设置网格项目位置。
grid-row: footer;
grid-column: footer;
简写的grid-row
和grid-column
也可以引用网格区域名称,设置网格项目的位置。
grid-area: sidebar;
grid-area
简写属性也可以引用网格区域的名称来设置网格项目的位置。
隐式网格
当网格项目确认在显式网格之外时就会创建隐性网格,当没有足够的空间或者显式的网格轨道来设置网格项目,此时网格项目就会自动创建隐式网格。
使用grid-auto-rows
、grid-auto-columns
和grid-auto-flow
属性可以定义隐式的网格。
grid-template-rows: 70px;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: 140px;
在这个例子中我们只定义了一行(轨道),所以item1
和item2
的高都是70px
。
第二行(轨道)自动创建了item3
和item4
空间。grid-auto-rows
定义隐式网格中的行(轨道)的大小,因此item3
和item4
的高度是140px
。
grid-auto-row: row
网格默认流方向是row
。
grid-auto-flow: column
也可以把网格流的方向改变成column
。
grid-template-columns: 30px 60px;
grid-auto-flow: column;
grid-auto-columns: 1fr;
在这个例子中,我们只定义了前两列的轨道尺寸。item1
的尺寸是30px
,item2
的尺寸是60px
。
使用grid-auto-flow:column
自动创建了隐式网格,用来放置item3
、item4
和item5
,并且这三个列(轨道)的尺寸由grid-auto-columns
来定义。
隐式地命名网格区域名称
通常可以将网格线命名成任何你想命名的名称,如果网格线名称添加-start
和-end
的后缀,其实也隐式的创建一个网格区域,可以用来设置网格项目的位置。
grid-template-rows: [outer-start] 1fr [inner-start] 1fr [inner-end] 1fr [outer-end];
grid-template-columns: [outer-start] 1fr [inner-start] 1fr [inner-end] 1fr [inner-end];
在这个示例中,行和列都具有inner-start
和inner-end
网格线名称,同时也对应的创建一个隐式网格区域名称inner
。
grid-area: inner
网格项目定位可以通过网格区域名称来设置,而不需要使用网格线名称。
隐式命名网格线名称
隐式的指定网格线反向指定了隐式的网格区域名称,命名的网格区域隐式的命名了网格线名称。
grid-template-areas: "header header"
"content sidebar"
"footer footer";
grid-template-rows: 80px 1fr 40px;
grid-template-columns: 1fr 200px;
指定网格区域会给网格区域边线添加隐式的网格线名称。这些网格线的命名是基于网格区域来命名,只是在网格区域名称的后面添加后缀-start
或-end
。
grid-row-start: header-start;
grid-row-end: content-start;
grid-column-start: footer-start;
grid-column-end: sidebar-end;
在这个示例中,header
通过隐式的网格线名称设置其位置。
网格项目层级
网格项目可以具有层级和堆栈,必要时可能通过z-index
属性来指定。
.item-1,
.item-2 {
grid-row-start: 1;
grid-column-end: span 2;
}
.item-1 {
grid-column-start: 1;
z-index: 1;
}
.item-2 {
grid-column-start: 2
}
在这个例子中,item1
和item2
的开始行都是1
,item1
列的开始是1
,item2
列的开始是2
,并且它们都跨越两列。两个网格项目都是由网格线数字定位,结果这两个网格项目重叠了。
默认情况下,item2
在item1
上面,但是,我们在item1
中设置了z-index:1;
,导致item1
在item2
之上。
grid-row-start: header-start;
grid-row-end: content-end;
grid-column-start: content-start;
grid-column-end: sidebar-start;
z-index: 1;
在这个示例中,一个网格项目定位和分层使用了grid-template-areas
定义的隐式网格线的名称。
网格项目对齐方式(Box Alignment)
CSS的Box Alignment Module补充了网格项目沿着网格行或列轴对齐方式。
justify-items
和justify-self
指定网格项目沿着行轴对齐方式;align-items
和align-self
指定网格项目沿着列轴对齐方式。
justify-items
和align-items
应用在网格容器上,它们的属性值有:
auto
normal
start
end
center
stretch
baseline
first baseline
last baseline
.grid {
grid-template-rows: 80px 80px;
grid-template-columns: 1fr 1fr;
grid-template-areas: "content content"
"content content";
}
.item {
grid-area: content
}
.grid {
justify-items: start
}
网格项目定位在行轴的开始位置(行网格线1
)。
justify-items: center
网格项目定位在行轴的中间。
justify-items: end
网格项目定位在行轴末端。
justify-items: stretch
网格项目横跨整个行轴,stretch
是justify-items
的默认值。
align-items: start
网格项目定位在网格列轴的开始位置(列网格线1
)。
align-items: center
网格项目定位在网格列轴中间。
align-items: end
网格项目定位在网格列轴末端。
align-items: stretch
网格项目横跨整个列。
justify-items: center
align-items: center
网格项目定位在网格行和列的中间(实现水平垂直居中)。
align-self
和justify-self
属性用于网格项目自身对齐方式。它们主要接受以下属性值:
auto
normal
start
end
center
stretch
baseline
first baseline
last baseline
.item-1 {
justify-self: start
}
.item-2 {
justify-self: center
}
.item-3 {
justify-self: end
}
justify-selft
指定网格项目自身沿着网格行轴的对齐方式。
.item-1 {
align-self: start
}
.item-2 {
align-self: center
}
.item-3 {
align-self: end
}
align-self
指定网格项目自身沿着列轴的对齐方式。
.item-1 {
justify-self: center
align-self: center
}
item1
项目定位在网格行和列轴的中间(实现水平垂直居中)。
网格轨道对齐方式
网格轨道对齐可以相对于网格容器行和列轴。
align-content
指定网格轨道沿着行轴对齐方式;justify-content
指定网格轨道沿着列轴对齐方式。它们支持下面属性:
normal
start
end
center
stretch
space-around
space-between
space-evenly
baseline
first baseline
last baseline
.grid {
width: 100%;
height: 300px;
grid-template-columns: repeat(4, 45px);
grid-template-rows: repeat(4, 45px);
grid-gap: 0.5em;
justify-content: start;
}
start
指定列沿着行轴开始排列,它是justify-content
默认值。
justify-content: end;
列沿着行末端开始排列。
justify-content: center;
列沿着行中间排列。
justify-content: space-around;
网格容器剩余列空间分配给每列的两端(相邻两列之间的间距是第一列与容器最左侧边缘或最后一列与容器最右侧边缘间距的两倍)。
justify-content: space-between;
网格容器剩余列空间平均分配给相邻的两列(第一列与容器最左侧边缘和最后一列与容器最右侧边缘没有任何间距)。
justify-content: space-evenly;
网格容器剩余列空间平均分配给列之间,相邻两列之间的间距与第一列和容器最左侧边级和最后一列与容器最右侧边缘间距相同。
align-content: start;
start
允许网格网从网格容器列轴的开始位置排列,其是align-content
的默认值。
align-content: end;
网格行在网格容器列轴末端。
align-content: center;
网格行在网格列中间。
align-content: space-around;
网格剩余行空间分配给每行之间上下,其中相邻两行的间距是第一行距离网格容器行顶端或者最后一行距离网格容器行末端之间间距的两倍。
align-content: space-between;
网格剩余行空间平均分配给相邻两行之间,其中第一行紧靠网格容器行的顶端,最后一行紧靠网格容器行的末端。
align-content: space-evenly;
网格剩余行空间平均分配给行之间,其中相邻两行的间距与第一行距容器行顶端间距和最后一行距容器末端的间距相等。
总结
这篇文章全面的介绍网格,就算不是一份完整的技术文档,也算是最全面、最简单介绍CSS Grid的一篇文章。而且都要比Mozilla的开发文档和W3C规范还要简单明了。
这里有一些CSS Grid的资料源:
- Complete Guide to Grid on CSS Tricks
- Grid by Example by Rachel Andrew
- The CSS Workshop by Jen Simmons
同时,在W3cplus.com上提供最全面的有关于CSS Grid的中文教程。
最后,CSS Grid规范文档还在不断的完善,而且我也是个容易犯错的人,如果文章中有何不对之处,可以在下面的评论中指正。当然,如果你有更好的有关于CSS Grid文档,欢迎在下面的评论中与我们一起分享。
本文根据@jonsuh的《Learn CSS Grid》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://learncssgrid.com/。
如需转载,烦请注明出处:https://www.fedev.cn/css/learncssgrid.htmlAir Jordan Trainer Essential