网页的布局方式千变万化,但是根本的技术就三种,从最开始的 table 布局到现在 div 布局,网页的呈现方式没变,背后的技术却发生很大的变化,这篇文章就来聊聊 CSS 网格 Web 布局完全指南。

这里给出的是 CSS 属性表,不是值不要搞错了。
CSS Grid 是目前 CSS 中可用的最强大的布局系统。不像 flexbox 的一维布局那样,这个二维布局系统可以操纵行和列。将父元素(网格容器 Grid Container)和子元素(网格项 Grid Items)分别设置CSS规则即可应用网格布局。
CSS网格布局(亦直接称为“网格”),这个一个二维网格基准的布局系统完全改变了我们传统创建网格布局界面方式。一直以来,我们用CSS设置我们的页面布局,但是从来都做得不够好。一开始我们用表格(tables),然后是浮动(floats),再是定位(postioning)和行内块(inline-block),但是这些方法都只是hack而已,还留下一大堆麻烦的功能性问题(比如垂直居中)。Flexbox在这其中脱颖而出,不过它只能在一维布局上有所建树,而在更加复杂的二维布局面前就显得力不从心了(Flexbox和Grid组合使用风味更佳)。网格(Grid)是第一个专门用来解决布局问题的CSS模块,我们终于不需要想尽办法hack页面布局样式了。
首先,你得定义一个包裹元素(container element),加上dispaly:grid样式,用grid-template-columns和grid-template-rows设置其子元素模板的【行】 【列】样式。
将子元素(child elements)放置到包裹元素之中,对这个子元素应用grid-column和gird-row样式。和flexbox类似的是,网格项的顺序并不重要。你的CSS可以将子元素设置任意的顺序,你还可以用媒体查询(media queries)非常方面地重排元素。想象一下,只要通过几行CSS代码就可以在各种屏幕上重排整个页面,网格布局绝对是有史以来最棒的CSS模块。
到2017年3月为止,很多浏览器已经原生支持而不用前缀定义的Grid属性:Chrome(包括Android),Firefox,Edge,Safari(包括IOS)和Opera。IE10和IE11虽然也能支持,但是它们实现的方式已经老掉牙了,还有一堆过时的语法。
在深入网格布局的概念之前,你需要理解一个非常重要的术语。我们这里要介绍的术语长得都非常相像,你如果不去理解其中的含义并记住它们,很快你就会晕头转向了,不过好在这些术语不是很多,现在让我们一起看看吧。
<div class="container">
<div class="item item-1"></div>
<div class="item item-2"></div>
<div class="item item-3"></div>
</div>
<div class="container">
<div class="item"></div>
<div class="item">
<p class="sub-item"></p>
</div>
<div class="item"></div>
</div>
本篇详细介网格属性表中的各个属性值和其用法。
.container {
display: grid | inline-grid | subgrid;
}
.container {
grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}
.container{
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}
填充<line-name>,用方括号把分隔线包起来。
.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];
}
.container {
grid-template-columns: repeat(3, 20px [col-start]) 5%;
}
/* 等价于 */
.container {
grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}
.container {
grid-template-columns: 1fr 1fr 1fr;
}
.container {
grid-template-columns: 1fr 50px 1fr 1fr;
}
.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 {
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";
}
以上代码生成一个4列3行的网格。整个第一行由header组成,第二行由main区域,空单元和一个sidebar区域组成。最后一行由footer组成。
.container {
grid-template: none | subgrid | <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";
}
.container {
grid-column-gap: <line-size>;
grid-row-gap: <line-size>;
}
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-column-gap: 10px;
grid-row-gap: 15px;
}
.container {
grid-gap: <grid-row-gap> <grid-column-gap>;
}
.container{
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-gap: 10px 15px;
}
如果grid-row-gap没有定义,那么就会等同grid-column-gap的值。
.container {
justify-items: start | end | center | stretch;
}
.container {
justify-items: start;
}
.container{
justify-items: end;
}
.container{
justify-items: center;
}
.container{
justify-items: stretch;
}
.container {
align-items: start | end | center | stretch;
}
.container {
align-items: start;
}
.container {
align-items: end;
}
.container {
align-items: center;
}
.container {
align-items: stretch;
}
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
.container {
justify-content: start;
}
.container {
justify-content: end;
}
.container {
justify-content: center;
}
.container {
justify-content: stretch;
}
.container {
justify-content: space-around;
}
.container {
justify-content: space-between;
}
.container {
justify-content: space-evenly;
}
.container {
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
.container {
align-content: start;
}
.container {
align-content: end;
}
.container {
align-content: center;
}
.container {
align-content: stretch;
}
.container {
align-content: space-around;
}
.container {
align-content: space-between;
}
.container {
align-content: space-evenly;
}
.container {
grid-auto-columns: <track-size> ...;
grid-auto-rows: <track-size> ...;
}
.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px
}
这里产生了一个2x2的网格但是想象一下,其中的网格项是这样用grid-column和grid-row定位的:
.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.item-b {
grid-column: 5 / 6;
grid-row: 2 / 3;
}
我们让.item-b定位在第5,6根列分隔线之中,但是我们并没有定义第5,6根分隔线。由于我们引用了不存在的分隔线,宽度为0的不可见网格轨道就填充了这个间隙。我们可以用grid-auto-columns和grid-auto-rows指定这些不可见网格轨道的尺寸。
.container {
grid-auto-columns: 60px;
}
.container {
grid-auto-flow: row | column | row dense | column dense
}
<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>
你定义了一个2行5列的网格,将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,所以我们的网格看起来会是这样。注意我们没有进行定位的3个网格项(item-b,item-c,item-d)会这样排列在可用的行中。
相反地,如果我们把grid-auto-flow设成了column,item-b,item-c,item-d会沿着列向下排列:
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: column;
}
.container {
grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
}
.container {
grid: 200px auto / 1fr auto 1fr;
}
/* 等价于 */
.container {
grid-template-rows: 200px auto;
grid-template-columns: 1fr auto 1fr;
grid-template-areas: none;
}
.container {
grid: column 1fr / auto;
}
/* 等价于 */
.container {
grid-auto-flow: column;
grid-auto-rows: 1fr;
grid-auto-columns: auto;
}
.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;
}
本篇详细介网格属性表中的各个属性值和其用法。
.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
}
.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
}
.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;
}
.item {
grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
.item-d {
grid-area: header
}
作为grid-row-start + grid-column-start + grid-row-end + grid-column-end属性的缩写形式
.item-d {
grid-area: 1 / col4-start / last-line / 6
}
.item-a {
justify-self: start;
}
.item-a {
justify-self: end;
}
.item-a {
justify-self: center;
}
.item-a {
justify-self: stretch;
}
.item{
align-self: start | end | center | stretch;
}
.item-a {
align****-self: start;
}
.item-a {
align-self: end;
}
.item-a {
align-self: center;
}
.item-a {
align-self: stretch;
}

