1、CSS Grid 简介
CSS
网格布局(又称 "网格 "或 "CSS网格"),是一种基于二维网格的布局系统,与过去的任何网页布局系统相比,它完全改变了我们设计用户界面的方式。它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样复杂的布局。以前,只能通过复杂的 CSS 框架达到的效果,现在浏览器内置了。
先来看一个以前我们稍觉得有点复杂的前端布局:
<div class="wrapper"> <header>Header</header> <aside>Aside</aside> <main>Main Content</main> <footer>Footer</footer> </div>
而现在使用 CSS Grid
,仅使用极少量的代码就能实现。
在兼容性方面,截至目前,几乎所有的浏览器都对 CSS Grid
提供了原生的支持(浏览器支持情况)。还不用起来更待何时~
要使用 CSS Grid
,你必须用 display: grid
定义一个容器元素为网格,用 grid-template-columns
和 grid-template-rows
设置列和行的大小,然后用 grid-column
和 grid-row
将其子元素放入网格。
2、几个重要的 CSS Grid 术语
在深入了解网格的概念之前,我们需要了解几个重要的术语。
2.1 容器(Grid Container)
Grid 容器
指的是应用 display: grid
的元素。它是所有网格项目的直接父元素。
下面这个例子中,container
是网格的容器:
<div class="container"> <div class="item item-1"></div> <div class="item item-2"></div> <div class="item item-3"></div> </div>
2.2 项目(Grid Items)
Grid 项目
指的是网格容器的直接后代元素。
下面这个例子中的 item
元素是网格项目,但 sub-item
不是:
<div class="container"> <div class="item"> </div> <div class="item"> <p class="sub-item"> </p> </div> <div class="item"> </div> </div>
2.3 网格线(Grid Lines)
网格线(Grid Lines)
指的是构成网格结构的分界线。它们可以是垂直的(“列网格线”)或水平的(“行网格线”),并且位于行或列的任一侧。请看下图:
2.4 单元格(Grid Cell)
单元格(Grid Cell)
指的是相邻两行和相邻两列网格线之间的空间。它是网格的一个 "单元"。
下面是行网格线1和2,列网格线2和3之间的网格单元:
2.5 网格轨道(Grid Tracks)
网格轨道(Grid Track)
指的是两条相邻网格线之间的空间。你可以把它们看成是网格的列或行。
下面是第1行和第2行网格线之间的网格轨迹:
2.6 网格区域(Grid Area)
网格区域(Grid Area)
指的是由四条网格线包围的总空间。一个网格区域可以由任何数量的网格单元组成。
下面是行网格线1和3,列网格线2和4之间的网格区域:
2.7 网格间距(Gaps)
网格间距(Gaps)
指的是轨道之间的间隙。为了确定尺寸,这些东西就像普通的轨道一样。你不能在缝隙中放置内容,但你可以将网格项目跨越它。
3、Grid 容器属性
3.1 display
将该元素定义为一个网格容器,并为其内容建立一个新的网格格式化上下文。
可选的值:
grid
:生成一个块状的网格inline-grid
:生成一个inline-level
的网格
.container { display: grid | inline-grid; }
通过嵌套元素(又称子网格)向下传递网格参数的能力已被移至 CSS网格规范的 Level 2。
详细的可看这里:传送门
3.2 grid-template-columns 和 grid-template-rows
容器指定了网格布局以后,接着就要划分行和列。grid-template-columns
属性定义每一列的列宽,grid-template-rows
属性定义每一行的行高。
可选的值:
<track-size>
:可以是一个长度、一个百分比,或者使用fr
单位表示网格中自由空间的一部分<line-name>
:一个你选择的任意的名字
.container { grid-template-columns: ... ...; /* e.g. 1fr 1fr minmax(10px, 1fr) 3fr repeat(5, 1fr) 50px auto 100px 1fr */ grid-template-rows: ... ...; /* e.g. min-content 1fr min-content 100px 1fr max-content */ }
网格线会从这些分配中自动分配正数(-1是最末一行的备用数)。
你可以选择明确地命名这些行。注意行名的括号语法。
.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]; }
请注意,一个行可以有一个以上的名字。例如,这里的第二行将有两个名字:row1-end
和 row2-start
。
.container { grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end]; }
如果你的定义包含重复的部分,你可以使用 repeat()
符号来简化。
.container { grid-template-columns: repeat(3, 20px [col-start]); }
它等同于:
.container { grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start]; }
如果多行同名,可以通过行名和计数来引用它们:
.item { grid-column-start: col-start 2; }
fr
允许你将轨道的大小设置为网格容器自由空间的一部分。例如,这将把每个项目设置为网格容器宽度的三分之一。
.container { grid-template-columns: 1fr 1fr 1fr; }
可用空间指的是非弹性项目之外的空间。在下面的示例中,fr 单位
可用的空间指的是除50px
之外的空间:
.container { grid-template-columns: 1fr 50px 1fr 1fr; }
3.3 grid-template-areas
通过引用 grid-area
属性指定的网格区域的名称,定义一个网格模板。重复一个网格区域的名称会使内容跨越这些单元格。一个句号表示一个空单元。语法本身提供了一个可视化的网格结构。
可选的值:
<grid-area-name>
:用grid-area指定的一个网格区域的名称。.
:句号表示一个空的网格单元none
:没有定义网格区域
.container { grid-template-areas: "<grid-area-name> | . | 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; 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
。
3.4 grid-template
这是 grid-template-rows
+ grid-template-columns
+ grid-template-areas
的简写。
可选的值:
none
:将所有三个属性设置为初始值<grid-template-rows>
/<grid-template-columns
>:将grid-template-columns
和grid-template-rows
分别设置为指定值,并将grid-template-areas
设置为none。
.container { grid-template: none | <grid-template-rows> / <grid-template-columns>; }
它还接受一种更复杂但相当方便的语法来指定所有这三种情况。下面是一个例子。
.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
。
还可以这样:
.container { display: grid; grid-template: "head head head" minmax(150px, auto) "sidebar content content" auto "sidebar footer footer" auto / 1fr 1fr 1fr; }
3.5 column-gap 和 row-gap
column-gap
(老的写法是 grid-column-gap
) 和 row-gap
(老的写法是 grid-row-gap
) 用来指定网格线的大小。你可以把它看作是设置列/行之间的沟槽的宽度。
可选的值:
<line-size>
:一个长度值
.container { /* 新的标准 */ column-gap: <line-size>; row-gap: <line-size>; /* 老的写法 */ grid-column-gap: <line-size>; grid-row-gap: <line-size>; }
例如:
.container { grid-template-columns: 100px 50px 100px; grid-template-rows: 80px auto 80px; column-gap: 10px; row-gap: 15px; }
gutters
只在列/行之间创建,而不是在外边缘。
注意:
grid-前缀
将被移除,grid-column-gap
和grid-row-gap
将被重新命名为column-gap
和row-gap
。在Chrome 68+
、Safari 11.2 Release 50+
和Opera 54+
中已经支持无前缀的属性。
3.6 gap
row-gap
和 column-gap
的简写。
可选的值:
<grid-row-gap>
<grid-column-gap>
:长度值
.container { /* 新的标准 */ gap: <grid-row-gap> <grid-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; }
如果没有指定 row-gap
,它将被设置为与 column-gap
相同的值。
注意:
grid-前缀
已被废弃(但谁知道呢,可能永远不会从浏览器中移除)。本质上,grid-gap
改名为gap
。在Chrome 68+
、Safari 11.2 Release 50+
和Opera 54+
中已经支持无前缀的属性。
3.7 justify-items
沿着内联(行)轴对齐网格项目(与沿着块(列)轴对齐的 align-items
相反)。这个值适用于容器内的所有网格项目。
可选的值:
start
:使项目与单元格的起始边缘齐平。end
:对齐项目,使其与单元格的末端边缘齐平center
:使项目在其单元格的中心位置对齐stretch
:填充整个单元格的宽度(这是默认值)
.container { justify-items: start | end | center | stretch; }
例如:
.container { justify-items: start; }
.container { justify-items: end; }
.container { justify-items: center; }
.container { justify-items: stretch; }
这种行为也可以通过 justify-self 属性在单个网格项目上设置。