by Chris House
译者:若愚老师
想要更好的阅读体验可在饥人谷技术博客 查看原文css
CSS 网格布局(Grid Layout) 是CSS中最强大的布局系统。 这是一个二维系统,这意味着它能够同时处理列和行,不像 flexbox 那样主要是一维系统。 你能够经过将CSS规则应用于父元素(成为网格容器)和该元素的子元素(网格元素),来使用网格布局。前端
CSS网格布局(又名“网格”)是一个二维的基于网格的布局系统,其目的只在于彻底改变咱们设计基于网格的用户界面的方式。 CSS一直用来布局网页,但一直都不完美。 一开始咱们使用table 作布局,而后转向浮动、定位以及inline-block,但全部这些方法本质上都是 Hack 的方式,而且遗漏了不少重要的功能(例如垂直居中)。 Flexbox的出如今必定程度上解决了这个问题,可是它的目的是为了更简单的一维布局,而不是复杂的二维布局(Flexbox和Grid实际上一块儿工做得很好)。 只要咱们一直在制做网站,咱们就一直在为解决布局问题不断探索, 而Grid是第一个专门为解决布局问题而生的CSS模块。面试
有两个东西,启发我写这篇指南。 第一个是雷切尔·安德鲁(Rachel Andrew)的书为CSS Grid布局准备。 这本书对网格布局作了完全、清晰的介绍,也是是整篇文章的基础,我强烈建议你购买并阅读他的书。 个人另外一个重要灵感是Chris Coyier的Flexbox彻底指南,当须要查阅 flexbox 的一切资料时我就会找这篇文章。 这篇文章帮助了不少人学习 Flex 布局,也是 Google 上搜索“flexbox”关键字排名第一的文章。你会发现他的文章和个人不少类似之处,有最好的范例在那放着为何咱不偷师学着写呢?算法
本指南的目的是介绍网格概念,由于它们存在于最新版本的规范中。 所以我不会覆盖过期的IE语法,并且随着规范的成熟,我会尽最大努力保存更新本指南。浏览器
一开始你须要使用display:grid
把容器元素定义为一个网格,使用grid-template-columns
和grid-template-rows
设置列和行大小,而后使用grid-column
和 grid-row
把它的子元素放入网格。 与flexbox相似,网格子元素的原始顺序不重要。 你的能够在 CSS 里以任意顺序放置它们,这使得使用媒体查询从新排列网格变得很是容易。 想象一下,咱们须要定义整个页面的布局,而后为了适应不一样的屏幕宽度彻底从新排列,咱们只须要几行CSS就能实现这个需求。 网格是有史以来最强大的CSS模块之一。微信
截至2017年3月,许多浏览器都提供了原生的、不加前缀的对CSS Grid的支持,好比 Chrome(包括Android),Firefox,Safari(包括iOS)和Opera。 另外一方面,Internet Explorer 10和11支持它,但须要使用过期的语法。 Edge浏览器已经宣布将支持标准的Grid语法,但暂未支持。ide
浏览器支持的详细数据可在 Caniuse查看。其中里面的数字表示该版本以上的浏览器支持Grid。
桌面浏览器布局
移动端 / 平板学习
除了微软以外,浏览器制造商在 Grid 规范彻底落地之前彷佛并无放手让 Gird 野生也长的打算。 这是一件好事,这意味着咱们不须要再去学习各类浏览器兼容版本的旧语法。flex
在生产环境中使用Grid只是时间问题,但如今是咱们该学习的时候了。
在深刻了解网格的概念以前,理解术语是很重要的。 因为这里所涉及的术语在概念上都是类似的,若是不先记住它们在网格规范中定义的含义,则很容易将它们彼此混淆。 可是不用太担忧,这些术语并很少。
设置了 display: gird
的元素。 这是全部grid item的直接父项。 在下面的例子中,.container
就是是 grid container。
<div class="container"> <div class="item item-1"></div> <div class="item item-2"></div> <div class="item item-3"></div> </div>
Grid 容器的孩子(直接子元素)。下面的 .item
元素就是 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>
这个分界线组成网格结构。 它们既能够是垂直的(“column grid lines”),也能够是水平的(“row grid lines”),并位于行或列的任一侧。 下面例中的黄线就是一个列网格线。
两个相邻网格线之间的空间。 你能够把它们想象成网格的列或行。 下面是第二行和第三行网格线之间的网格轨道。
两个相邻的行和两个相邻的列网格线之间的空间。它是网格的一个“单元”。 下面是行网格线1和2之间以及列网格线2和3的网格单元。
四个网格线包围的总空间。 网格区域能够由任意数量的网格单元组成。 下面是行网格线1和3以及列网格线1和3之间的网格区域。
Grid Container 的所有属性
Grid Items 的所有属性
将元素定义为 grid contaienr,并为其内容创建新的网格格式化上下文(grid formatting context)。
值:
.container { display: grid | inline-grid | subgrid; }
注意:column
, float
, clear
, 以及 vertical-align
对一个 grid container 没有影响
使用以空格分隔的多个值来定义网格的列和行。这些值表示轨道大小(track size),它们之间的空格表明表格线(grid line)。
.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; }
但你能够给网格线指定确切的命名。 注意中括号里的网格线命名语法:
.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]; }
须要注意的是,一个网格线能够有不止一个名字。例如,这里第2条网格线有两个名字: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]) 5%; }
上面的写法和下面等价:
.container { grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%; }
“fr”单位容许您将轨道大小设置为网格容器自由空间的一部分。 例如,下面的代码会将每一个 grid item 为 grid container 宽度的三分之一:
.container { grid-template-columns: 1fr 1fr 1fr; }
自由空间是在排除全部不可伸缩的 grid item 以后计算获得的。 在下面的示例中,fr单位可用的自由空间总量不包括50px:
.container { grid-template-columns: 1fr 50px 1fr 1fr; }
经过引用 grid-area
属性指定的网格区域的名称来定义网格模板。 重复网格区域的名称致使内容扩展到这些单元格。 点号表示一个空单元格。 语法自己提供了网格结构的可视化。
值:
<grid-area-name>
- 使用 grid-area 属性设置的网格区域的名称举例:
.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"; }
这将建立一个四列宽三行高的网格。 整个第一行将由 header 区域组成。 中间一行将由两个 main 区域、一个空单元格和一个 sidebar 区域组成。 最后一行是footer区域组成。
你的声明中的每一行都须要有相同数量的单元格。
您可使用任意数量的相邻的.来声明单个空单元格。 只要这些点号之间没有空格,他们就表明了一个单一的单元格。
须要注意的是你不是在用这个语法命名网格线,而是在命名区域。 当你使用这种语法时,区域两端的网格线其实是自动命名的。 好比,若是网格区域的名称是foo,那么区域的起始的行网格线和列网格线名称是 foo-start,而且区域终点的行网格线和列网格线名称是 foo-end。 这意味着某些网格线可能有多个名称,好比上面的例子中最左边的一条网格线有三个名字:header-start,main-start 和 footer-start。
在单个声明中定义 grid-template-rows、grid-template-columns、grid-template-areas 的简写。
值:
grid-template-rows
/ <grid-template-columns
- 把 grid-template-columns 和 grid-template-rows 设置为指定值, 与此同时, 设置 grid-template-areas 为 none.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"; }
因为 grid-template 不会重置隐式网格属性(grid-auto-columns
,grid-auto-rows
和grid-auto-flow
),而这多是大多数状况下你想要作的。所以建议使用grid属性来代替grid-template
。
指定网格线的大小,你能够把它想象为设置列/行之间的间距的宽度。
值:
line-size
- 一个长度值.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; }
只能在列/行之间建立缝隙,而不是在外部边缘建立。
grid-row-gap 和 grid-column-gap 的缩写
.container { grid-gap: <grid-row-gap> <grid-column-gap>; }
Example:
.container { grid-template-columns: 100px 50px 100px; grid-template-rows: 80px auto 80px; grid-gap: 10px 15px; }
若是没有指定 grid-row-gap,则会被设置为与 grid-column-gap 相同的值。
沿着行轴对齐网格内的内容(与之对应的是 align-items, 即沿着列轴对齐),该值适用于容器内的全部的 grid items。
值:
.container { justify-items: start | end | center | stretch; }
举例:
.container { justify-items: start; }
.container{ justify-items: end; }
.container { justify-items: center; }
.container { justify-items: stretch; }
也能够经过给单个 grid item 设置justify-self
属性来达到上述效果。
沿着列轴对齐grid item 里的内容(与之对应的是使用 justify-items 设置沿着行轴对齐),该值适用于容器内的全部 grid items。
值:
.container { align-items: start | end | center | stretch; }
举例:
.container { align-items: start; }
.container { align-items: end; }
.container { align-items: center; }
.container { align-items: stretch; }
也能够经过给单个 grid item 设置align-self
属性来达到上述效果。
有时,网格的总大小可能小于其网格容器的大小。若是你的全部 grid items 都使用像px这样的非弹性单位来设置大小,则可能发生这种状况。此时,你能够设置网格容器内的网格的对齐方式。 此属性沿着行轴对齐网格(与之对应的是 align-content, 沿着列轴对齐)。
值:
.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; }
有时,网格的总大小可能小于其网格容器的大小。若是你的全部 grid items 都使用像px这样的非弹性单位来设置大小,则可能发生这种状况。此时,你能够设置网格容器内的网格的对齐方式。 此属性沿着列轴对齐网格(与之对应的是 justify-content, 即沿着行轴对齐)。
值:
.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; }
指定自动生成的网格轨道(又名隐式网格轨道)的大小。 隐式网格轨道在你显式的定位超出指定网格范围的行或列(使用 grid-template-rows/grid-template-columns)时被建立。
值:
<track-size>
- 能够是一个长度值,一个百分比值,或者一个自由空间的一部分(使用 fr 单位).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; }
若是你存在没有显示指明放置在网格上的 grid item,则自动放置算法会自动放置这些项目。 而该属性则用于控制自动布局算法的工做方式。
值:
.container { grid-auto-flow: row | column | row dense | column dense }
须要注意的是,dense 可能致使您的 grid item 乱序。
举例, 考虑以下 HTML:
<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; }
当把 grid item 放在网格上时,你只把其中两个设置了固定的位置:
.item-a { grid-column: 1; grid-row: 1 / 3; } .item-e { grid-column: 5; grid-row: 1 / 3; }
由于咱们将 grid-auto-flow 设置为row,因此咱们的grid就像这样。 注意观察咱们没有作设置的三个项目(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; }
在单个属性中设置全部如下属性的简写:grid-template-rows,grid-template-columns,grid-template-areas,grid-auto-rows,grid-auto-columns和grid-auto-flow。 它同时也将 sets grid-column-gap 和 grid-row-gap 设置为它们的初始值,即便它们不能被此属性显示设置。
值:
<grid-template-rows>
/ <grid-template-columns>
- 将 grid-template-rows 和 grid-template-columns 分别设置为指定值,将全部其余子属性设置为其初始值<grid-auto-flow>
[<grid-auto-rows>
[ / <grid-auto-columns>
] ] - 接受全部与grid-auto-flow,grid-auto-rows和grid-auto-columns相同的值。 若是省略grid-auto-columns,则将其设置为为grid-auto-rows指定的值。 若是二者都被省略,则它们被设置为它们的初始值.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; }
它也可用使用一个更复杂但至关方便的语法来一次设置全部内容。 你能够指定 grid-template-areas、grid-template-rows 以及 grid-template-columns,并将全部其余子属性设置为其初始值。 你如今所作的是在其网格区域内,指定网格线名称和内联轨道大小。 能够看下面的例子:
.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; }
使用特定的网格线肯定 grid item 在网格内的位置。grid-column-start/grid-row-start 属性表示grid item的网格线的起始位置,grid-column-end/grid-row-end属性表示网格项的网格线的终止位置。
值:
<line>
: 能够是一个数字来指代相应编号的网格线,也可以使用名称指代相应命名的网格线span <number>
: 网格项将跨越指定数量的网格轨道span <name>
: 网格项将跨越一些轨道,直到碰到指定命名的网格线.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 }
若是没有声明 grid-column-end / grid-row-end,默认状况下,该网格项将跨越1个轨道。
网格项能够相互重叠。 您可使用z-index来控制它们的堆叠顺序。
grid-column-start + grid-column-end, 和 grid-row-start + grid-row-end 的简写形式。
值:
<start-line>
/ <end-line>
- 每一个值的用法都和属性分开写时的用法同样.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; }
若是没有指定结束行值,则该网格项默认跨越1个轨道。
给 grid item 进行命名以便于使用 grid-template-areas 属性建立模板时来进行引用。另外也能够作为 grid-row-start + grid-column-start + grid-row-end + grid-column-end 的简写形式。
值:
<name>
- 你的命名<row-start>
/ <column-start>
/ <row-end>
/<column-end>
- 能够是数字,也能够是网格线的名字.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 }
沿着行轴对齐grid item 里的内容(与之对应的是 align-self, 即沿列轴对齐)。 此属性对单个网格项内的内容生效。
值:
举例:
.item-a { justify-self: start; }
.item-a { justify-self: end; }
.item-a { justify-self: center; }
.item-a { justify-self: stretch; }
要为网格中的全部grid items 设置对齐方式,也能够经过 justify-items 属性在网格容器上设置此行为。
沿着列轴对齐grid item 里的内容(与之对应的是 justify-self, 即沿行轴对齐)。 此属性对单个网格项内的内容生效。
值:
.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; }
要为网格中的全部grid items 统一设置对齐方式,也能够经过 align-items 属性在网格容器上设置此行为。
加微信号: astak10或者长按识别下方二维码进入前端技术交流群 ,暗号:写代码啦
每日一题,每周资源推荐,精彩博客推荐,工做、笔试、面试经验交流解答,免费直播课,群友轻分享... ,数不尽的福利免费送