Grid布局指南

翻译

简介
CSS网格布局(又称“网格”),是一种二维网格布局系统。CSS在处理网页布局方面一直做的不是很好。一开始我们用的是table(表格)布局,然后用float(浮动),position(定位)和inline-block(行内块)布局,但是这些方法本质上是hack,遗漏了很多功能,例如垂直居中。后来出了flexbox(盒子布局),解决了很多布局问题,但是它仅仅是一维布局,而不是复杂的二维布局,实际上它们(flexbox与grid)能很好的配合使用。Grid布局是第一个专门为解决布局问题而创建的CSS模块,2012年11月06日成立草案

初步了解和浏览器支持
使用Grid布局非常简单,你只需要给容器(container)定义:display:grid,并设置列(grid-template-columns)和 行(grid-template-rows)的大小,然后用grid-column和grid-row定义容器子元素(grid-item项目)的位置。与flexbox布局类似,一开始项目的排列顺序并不重要,可以放置在容器的任何位置,这也使得你非常容易通过媒体查询重新排列你的项目。想象一下,当你定义整个页面的布局时,你只需要几行CSS就可以完成页面重排以便适应各种屏幕宽度,这得有多么神奇!
好东西总是来的晚,不要焦躁,不要沮丧。活好每一天,自然就等到了。
目前浏览器还不支持Grid布局,IE10和IE11支持老的语法。如果你想体验Grid布局的强大,推荐使用开通过“体验新功能”的Chrome, Opera 或 Firefox, Chrome:打开浏览器,输入chrome://flags,找到"experimental web platform features",启用并重启浏览器;Opera:输入opera://flags,与Chrome一样;Firefox:输入layout.css.grid.enabled。

浏览器支持情况:

Chrome|Safari|Firefox|Opera|IE|Android/iOS
-|-|--|-|-
29+ (Behind flag)|Not supported|40+ (Behind flag)|28+ (Behind flag)|10+ (Old syntax)|Not supported

重要术语
在深入了解Grid布局概念之前,我们先了解一些术语。因为这些术语在概念上很相似,如果你不记住Grid定义的含义,会很容易将它们混淆,但是不用担心,这里术语很少。

1.网格容器(Grid Container)
元素应用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.网格项(Grid Item)
网格容器的子元素,下面的item元素是网格项,但sub-item不是。

<div class="container">
  <div class="item"></div> 
  <div class="item">
    <p class="sub-item"></p>
  </div>
  <div class="item"></div>
</div>

3.网格线(Grid Line)
组成网格线的分界线。它们可以是列网格线(column grid lines),也可以是行网格线(row grid lines)并且居于行或列的任意一侧,下面黄色线就是列网格线。

grid lines

4.网格轨道(Grid Track)
两个相邻的网格线之间为网格轨道。你可以认为它们是网格的列或行,下面在第二个和第三个网格线之间的黄色部分为网格轨道。

Grid Track

5.网格单元(Grid Cell)
两个相邻的列网格线和两个相邻的行网格线组成的是网格单元,它是最小的网格单元。下面行网格线1(row grid lines 1)、行网格线2(row grid lines 2)和列网格线2(column grid lines 2)、列网格线3(column grid lines 3)组成的黄色区域为网格单元。

Grid Cell

6.网格区(Grid Area)
网格区是由任意数量网格单元组成,下面行网格线1(row grid lines 1)、行网格线3(row grid lines 3)和列网格线1(column grid lines 1)、列网格线3(column grid lines3)组成的黄色区域为网格区。

Grid Area

设置在网格容器上的属性

  • display
  • grid-template-columns
  • grid-template-rows
  • grid-template-areas
  • grid-column-gap
  • grid-row-gap
  • grid-gap
  • justify-items
  • align-items
  • justify-content
  • align-content
  • grid-auto-columns
  • grid-auto-rows
  • grid-auto-flow
  • grid

1. display: grid | inline-grid | subgrid;

属性值:
grid: 生成块级网格
inline-grid: 生成行内网格
subgrid: 如果网格容器本身是网格项(嵌套网格容器),此属性用来继承其父网格容器的列、行大小。

注:当元素设置了网格布局,column、float、clear、vertical-align属性无效。

2. grid-template-columns: <track-size> ... | <line-name> <track-size> ... ;
grid-template-rows: <track-size> ... | <line-name> <track-size> ... ;

设置行和列的大小,在行轨道或列轨道两边是网格线。

属性值:
track-size: 轨道大小,可以使用css长度,百分比或用分数(用fr单位)。
line-name: 网格线名字,你可以选择任何名字。

例子:
当你设置行或列大小为auto时,网格会自动分配空间和网格线名称。

.container{
    display:grid;
    grid-template-columns: 40px 50px auto 50px 40px;
    grid-template-rows: 25% 100px auto;
}
grid-numbers

你也可以给网格线定义名字,注意名字需要写在[]里面。

.container{
    display:grid;
    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];
}
grid-names

每条网格线可以有多个名字,例如上面行的第二条线有两个名字,分别是row1-end和row2-start。

.container{
    display:grid;
    grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

如果你定义包含重复部分,可以使用repeat()简化。

.container{
    display:grid;
    grid-template-columns: repeat(3, 20px [col-start]) 5%;
}

上面等同于下面:

.container{
    display:grid;
    grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}

用fr单位可以将容器分为几等份,例如下面分成三等份。

.container{
    display:grid;
    grid-template-columns: 1fr 1fr 1fr;
}

如果fr单位和实际值一起使用,设置fr的行或列将分(除了实际值)剩余部分。

.container{
    display:grid;
    grid-template-columns: 1fr 50px 1fr 1fr;
}

3.grid-template-areas

通过获取网格项中的grid-area属性值(名称),来定义网格模版。重复网格区(grid-area)名称将跨越网格单元格,‘.’代表空网格单元。

属性值:
grid-area-name: 网格项的grid-area属性值(名字)
‘.’ : 空网格单元
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"
}

上面代码示例会创建四列三行网格,第一行将是header,第二行前两个网格单元是main部分、第三个为空网格单元、第四个为sliderbar,第三行是footer。

grid-template-areas

4. grid-column-gap:<line-size>; 和 grid-row-gap: <line-size> ;

网格单元间距。

属性值:
line-size: 网格线间距,设置单位值。

例子:

.container{
    display:grid;
    grid-template-columns: 100px 50px 100px;
    grid-template-rows: 80px auto 80px; 
    grid-column-gap: 10px;
    grid-row-gap: 15px;
}
grid-column-row-gap

注:间隔仅仅作用在网格单元之间,不作用在容器边缘。

5. grid-gap:<grid-row-gap> <grid-column-gap>;

是grid-column-gap 和 grid-row-gap简写。

例子:

.container{
    display:grid;
    grid-template-columns: 100px 50px 100px;
    grid-template-rows: 80px auto 80px; 
    grid-gap: 10px 15px;
}

注:如果只设置一个值,那么grid-column-gap 和 grid-row-gap都为那个值。

6. justify-items: start | end | center | stretch(默认) ;

垂直于列网格线对齐,适用于网格容器里的所有网格项。

属性值:
start: 左对齐。
end: 右对齐。
center: 居中对齐。
stretch: 填满(默认)。

例子:

.container{
    display:grid;
    justify-items: start;
}
grid-justify-items-start
.container{
    display:grid;
    justify-items: end;
}
grid-justify-items-end
.container{
    display:grid;
    justify-items: center;
}
grid-justify-items-center
.container{
    display:grid;
    justify-items: stretch;
}
grid-justify-items-stretch

7. align-items: start | end | center | stretch ;

垂直于行网格线对齐,适用于网格容器里的所有网格项。

属性值:
start: 顶部对齐。
end: 底部对齐。
center: 居中对齐。
stretch:填满(默认)。

例子:

.container{
    display:grid;
    align-items: start;
}
grid-align-items-start
.container{
    display:grid;
    align-items: end;
}
grid-align-items-end
.container{
    display:grid;
    align-items: center;
}
grid-align-items-center
.container{
    display:grid;
    align-items: stretch;
}
grid-align-items-stretch

8. justify-content: start | end | center | stretch | space-around | space-between | space-evenly ;

如果用像px非弹性单位定义的话,总网格区域大小有可能小于网格容器,这时候你可以设置网格的对齐方式(垂直于列网格线对齐)。

属性值:
start: 左对齐。
end: 右对齐。
center: 居中对齐。
stretch: 填满网格容器。
space-around: 网格项两边间距相等,网格项之间间隔是单侧的2倍。
space-between: 两边对齐,网格项之间间隔相等。
space-evenly: 网格项间隔相等。

例子:

.container{
    display:grid;
    justify-content: start;
}
grid-justify-content-start
.container{
    display:grid;
    justify-content: end;
}
grid-justify-content-end
.container{
    display:grid;
    justify-content: center;
}
grid-justify-content-center
.container{
    display:grid;
    justify-content: stretch;
}
grid-justify-content-stretch
.container{
    display:grid;
    justify-content: space-around;
}
grid-justify-content-space-around
.container{
    display:grid;
    justify-content: space-between;
}
grid-justify-content-space-between
.container{
    display:grid;
    justify-content: space-evenly;
}
grid-justify-content-space-evenly

9. align-content: start | end | center | stretch | space-around | space-between | space-evenly ;

如果用像px非弹性单位定义的话,总网格区域大小有可能小于网格容器,这时候你可以设置网格的对齐方式(垂直于行网格线对齐)。

属性值:
start: 顶部对齐。
end: 底部对齐。
center: 居中对齐。
stretch: 填满网格容器。
space-around: 网格项两边间距相等,网格项之间间隔是单侧的2倍。
space-between: 两边对齐,网格项之间间隔相等。
space-evenly: 网格项间隔相等。

例子:

.container{
    display:grid;
    align-content: start; 
}
grid-align-content-start
.container{
    display:grid;
    align-content: end; 
}
grid-align-content-end
.container{
    display:grid;
    align-content: center; 
}
grid-align-content-center
.container{
    display:grid;
    align-content: stretch; 
}
grid-align-content-stretch
.container{
    display:grid;
    align-content: space-around; 
}
grid-align-content-space-around
.container{
    display:grid;
    align-content: space-between; 
}
grid-align-content-space-between
.container{
    display:grid;
    align-content: space-evenly; 
}
grid-align-content-space-evenly

10. grid-auto-columns: <track-size> ... ; 和 grid-auto-rows: <track-size> ... ;

自动生成隐式网格轨道(列和行),当你定位网格项超出网格容器范围时,将自动创建隐式网格轨道。

属性值:
track-size: 网格轨道大小,可以是固定值,百分比或者是分数(fr单位)。

为了说明隐式网格轨道是怎么创建的,我们先看下面列子:

.container{
    display:grid;
    grid-template-columns: 60px 60px;
    grid-template-rows: 90px 90px
}
grid-auto

这是2✖️2的网格,但是我们来用grid-column 和 grid-row给网格项定位如下:

.item-a{
    grid-column: 1 / 2;
    grid-row: 2 / 3;
}
.item-b{
    grid-column: 5 / 6;
    grid-row: 2 / 3;
}
implicit-tracks

我们可以看出,网格项item-b定位在第五根列网格线(column line 5 )和第六根列网格线(column line 6 )之间。但是我们网格容器根本不存在这两条网格线,所以就用两个0宽度来填充。在这里我们可以用网格自动行(grid-auto-rows)和网格自动列(grid-auto-columns)来定义这些隐式轨道宽度。

.container{
    display:grid;
    grid-auto-columns: 60px;
}
implicit-tracks-with-widths

11. grid-auto-flow : row(默认) | column | dense ;

在没有设置网格项的位置时,这个属性控制网格项怎样排列。

属性值:
row: 按照行依次从左到右排列。
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>

下面定义5列2行网格,同时定义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,item-b、item-c和item-d在行上是从左到右排列,如下:

grid-auto-flow-row

如果我们设置 grid-auto-flow: column;结果如下:

grid-auto-flow-column

12. grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [ / <grid-auto-columns>] ];

是一种简写形式,设置网格容器所有属性。

属性值:
none: 设置为所有属性的默认值。
<grid-template-rows> / <grid-template-columns>: 设置行和列的值,其他属性为默认值。
<grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns>] ] : 设置网格自动流、网格自动行、网格自动列的值,其他未设置则为默认值。

例子1:

.container{
    grid: 200px auto / 1fr auto 1fr;
}
等同于
.container{
    grid-template-rows: 200px auto;
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: none;
}

例子2:

.container{
    grid: column 1fr / auto;
}
等同于
.container{
    grid-auto-flow: column;
    grid-auto-rows: 1fr;
    grid-auto-columns: auto;
}

设置在网格项上的属性

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end
  • grid-column
  • grid-row
  • grid-area
  • justify-self
  • align-self


1. 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 ;

通过网格线来定义网格项的位置。grid-column-start、grid-row-start定义网格项的开始位置,grid-column-end、grid-row-end定义网格项的结束位置。

属性值:
line: 指定带编号或者名字的网格线。
span <number>: 跨越轨道的数量。
span <name>: 跨越轨道直到对应名字的网格线。
auto: 自动展示位置,默认跨度为1。

例子:

.item-a{
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start
  grid-row-end: 3
}
grid-start-end-a
.item-b{
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2
  grid-row-end: span 2
}
grid-start-end-a

注:如果未声明grid-column-end或grid-row-end,默认将跨越一个轨道。项目也可以重叠,设置z-index来确定堆叠顺序。

2. grid-column: <start-line> / <end-line> | <start-line> / span <value> ;
     grid-row: <start-line> / <end-line> | <start-line> / span <value> ;

是 grid-column-start、grid-column-end 和 grid-row-start、grid-row-end 的简写。

例子:

.item-c{
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}
grid-start-end-c

3. grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end> ;

定义网格项名字,以便创建模块(容器属性grid-template-areas来定义模块)。

属性值:
name: 项目名子。
<row-start> / <column-start> / <row-end> / <column-end>: 可以是数字或网格线名字。

例子:
定义网格项名字:

.item-d{
  grid-area: header
}

通过网格线定位网格项:

.item-d{
  grid-area: 1 / col4-start / last-line / 6 ;
}
grid-start-end-d

4. justify-self: justify-self: start | end | center | stretch;

定义单个网格项垂直于列网格线的对齐方式。

属性值:
start: 网格区域左对齐。
end: 网格区域右对齐。
center: 网格区域居中。
stretch: 网格区域填满。

例子:

.item-a{
  justify-self: start;
}
grid-justify-self-start
.item-a{
  justify-self: end;
}
grid-justify-self-end
.item-a{
  justify-self: center;
}
grid-justify-self-center
.item-a{
  justify-self: stretch;
}
grid-justify-self-stretch

提示:也可以在容器上设置justify-items,达到全部网格项对齐。

5. align-self: start | end | center | stretch;

定义单个网格项垂直于行网格线的对齐方式。

属性值:
start: 网格区域顶部对齐。
end: 网格区域底部对齐。
center: 网格区域居中。
stretch: 网格区域填满。

例子:

.item-a{
  align-self: start;
}
grid-align-self-start
.item-a{
  align-self: end;
}
grid-align-self-end
.item-a{
  align-self: center;
}
grid-align-self-center
.item-a{
  align-self: stretch;
}
grid-align-self-stretch

提示:也可以在容器上设置align-items,达到全部网格项对齐。

结束

这篇文章翻译自A Complete Guide to Grid,作者是CHRIS HOUSE。里面也加入了一些我个人的理解。文章有点长,属性容易混淆,边看边练习会比较容易理解和记住。

本文来自博客: http://peale.cn/

古人学问无遗力,少壮工夫老始成。
纸上得来终觉浅,绝知此事要躬行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,565评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,021评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,003评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,015评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,020评论 5 370
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,856评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,178评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,824评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,264评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,788评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,913评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,535评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,130评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,102评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,334评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,298评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,622评论 2 343

推荐阅读更多精彩内容