注:此文是我翻译的第一篇技术文章。适合有必定CSS原生网格布局使用经验的开发者(读前须要先去了解一下原生CSS网格的语法),原生CSS网格布局(Native CSS grid)截止目前尚未被任何正式版本的浏览器实现。原文地址css
_如下是来自Oliver Williams的帖子. Oliver已经学习了至关长时间的原生CSS网格,能够说是在CSS网格方面有必定的发言权。在这篇文章中,他将以非同寻常的思路分析本身的CSS网格布局学习之路。我比较赞同他的想法,就是学习一门新技术的时候,把它们拆分红比较小的单元块并配上实例,一步一步的学习。这比直接学习网格布局的全部东西要好太多了。html
浏览器原生CSS网格预计会在2017年年初获得支持. 在这以前你须要在浏览器中开启这个实验性的功能 (Firefox实验版默认是开启的). Chrome Canary是当前最好的实现. 同时,火狐有一个很是好的插件叫CSS Grid Inspector, 它能显示出网格的线,它是目前惟一能够在浏览器中运行的此类工具。web
在 chrome的地址栏中输入chrome://flags
, 找到 ‘实验性网络平台功能’ 并开启它. IE 和 Edge 实现的是一个比较老的网格标准,如今并不受支持。算法
相信我,很快你就能掌握它的.chrome
网格布局只能像左边那样,以矩形的单元块组合起来。并不能像右图那样,由一堆零散的多边形(跟俄罗斯方块那样的块)拼凑。浏览器
虽然网格布局和弹性盒在某些方面起到类似的做用,并且你能够发现,不少人用弹性盒来实现网格布局,但这并非设计弹性盒的初衷。Jake Archibald的这篇博文值得一读_Don't use flexbox for overall page layout。网络
这篇博文大概的意思是:app
Flexbox(弹性盒)是为一维布局设计的(行或列)。框架
CSS网格是为二维设计的.less
Rachel Andrews也 说过相似的话:
Flexbox(弹性盒)用于一维布局 – 也就是行或者列. 网格用于二维布局 – 也就是多行多列.
它们能够很好的结合,你能够往弹性容器中放入网格,也能够在网格块中加入flex元素
来看个例子吧。 咱们想在一个网格元素(grid item)里垂直居中一段文字, 但咱们想要让背景(图片,颜色或渐变)覆盖整个的网格区域。 咱们可使用align-items
属性,并把它的值设为center,可是若是这样背景并不会填满整个网格元素的区域。align-items
默认的值是 stretch
-你不改变它,始终会填满整个空间的。咱们把网格元素设为align-items:center
并把网格元素(grid item)设置为一个弹性容器(flex container)。
.grid { align-items: stretch; } .griditem { display: flex; align-items: center; }
在小屏幕下,写一个12列的网格,全部格子的跨度都12列。
你能够用网格这样作:
/* For small screens */ .span4, .span6, .spanAll { grid-column-end: span 12; } /* For large screens */ @media (min-width: 650px) { .span4 { grid-column-end: span 4; } .span6 { grid-column-end: span 6; } }
这样的显示效果是没什么错误的,当使用CSS网格,从新定义列数很是简单。而且你能够经过设置grid-column-end: -1;
来让你的页面始终是从左到右贯穿的。
/* For small screens */ .span4, .span6, .spanAll { grid-column-end: -1; }
在大屏幕上,你想要尽量的接近12列,可是在移动端,一行大概是1~4列。用media来改变grid-template-columns
是很是容易的。
.grid { grid-template-columns: 1fr 1fr; } @media (min-width: 700px) { .grid { grid-template-columns: repeat(12, 1fr); } }
有一些元素,咱们想让它贯穿整个视口,好比像 header, footer,和一些大图啥的。
对于小屏幕,咱们能够这样写:
.wide { grid-column: 1 / 3; /* start at 1, end at 3 */ }
不幸的是,当咱们换到大屏的时候,一行12列,这些元素将仅仅占满前两列,并不会占满12列,咱们须要定义新的grid-column-end
,而且把他的值设为 13
. 这种方式比较麻烦,还有一种简单的方式,grid-column: 1 / -1;
,这样不论在什么屏幕尺寸下,它们都是占满整行的了。就像下面这样:
.wide, .hero, .header, .footer { grid-column: 1 / -1; }
See the Pen Easier media queries with -1 by CSS GRID (@cssgrid) on CodePen.
使用grid-template-areas
和grid-line-numbers
是两种控制行数的属性,你也能够两个同时用。你可使用那些隐含的行名去设置你的网格。
.grid { grid-template-areas: "main main sidebar sidebar"; }
这段代码,咱们能获得四个隐含名字,main-start, main-end, sidebar-start, 和 sidebar-end.
这可能颇有用,若是你想重叠内容,不管是在几个网格区域或在一个特定分段的网格区域。
See the Pen implicit line names with grid areas by CSS GRID (@cssgrid) on CodePen.
就像给网格的行命名,特殊的行名能用于设置网格区域,语法是这样的:
.grid { grid-template-areas: "header header header" "main main sidebar" "footer footer footer"; } 、
若是你的布局设计(太多列的布局!没列都要起名字,可能还须要空元素)中有不少空的区域,这种写法稍微有点麻烦。因此对于网格是有另外一种写法的,在这种写法中,名字是什么无所谓,只要你合理利用到[name-start]
和 [name-end]
,也能达到本身的布局目的。下面是一个例子:
.grid { display: grid; grid-template-columns: 20px 100px [main-start] 1fr [main-end] 100px 20px; grid-template-rows: 100px [main-start] 100px [main-end] 100px; } .griditem1 { background-color: red; grid-area: main; }
See the Pen Another way of defining grid-areas by CSS GRID (@cssgrid) on CodePen.
你可能并不想整个页面都用这种方式布局,可是若是你想要结合 grid-area
来肯定行数的话,它会很是适合。
虽然你能够在CSS网格中使用任意尺寸的行或列,可是若是想要相等大小的格子并是响应式的,你就须要使用vmin单位了。
.grid { grid-template-columns: repeat(5, 20vw); grid-template-rows: repeat(5, 20vh); }
这种布局在台式电脑和笔记本上基本均可以完美显示,可是在手机上,高度大于宽,内容将会溢出,产生出一个横向的滚动条。Dudley Storey写了篇blog说这件事the usefulness of a lesser-known css unit: vmin。这种方法,经过调整容器视口的百分比和内容位置,作到适配各类尺寸的屏幕。
.gridcontainer { display: grid; width: 100vw; height: 100vh; justify-content: center; align-content: center; grid-template-columns: repeat(5, 20vmin); grid-template-rows: repeat(5, 20vmin); }
See the Pen Boxy Layout with CSS Grid and vmin by CSS GRID (@cssgrid) on CodePen.
当咱们绝对定位一个网格元素的时候,这个元素会跑到它的容器中,咱们能够用grid-column 和 grid-row来定位它。正常状况下,绝对定位使元素脱离文档流,它最适合的使用场景就是想要让元素重叠,并不打乱其余布局元素。除非你为每一个元素声明grid-column-start
和 grid-row-start
,要否则即便使用了绝对定位,元素也是不会重叠的。
尝试删除这个例子中div的position: absolute;
,思考grid-column 和 grid-row的值,也能够试试修改它们,你就明白是什么意思了。
See the Pen preserving auto-placement with position: absolute by CSS GRID (@cssgrid) on CodePen.
若是你使用过弹性盒(flexbox)的order
属性,那你已经知道一些相关的知识了。全部的网格元素都有一个默认的order值0。因此若是给一个网格元素设置 order: 1;
,这个元素将在全部元素的后面。 你能够给order
属性设置负值,让它跑到全部item的前面。
See the Pen Order value by CSS GRID (@cssgrid) on CodePen.
想不想要整行随着内容的宽度而变宽,直到他们达到最大宽度,这种状况你可能想尝试使用 minmax()
:
.grid { display: grid; grid-template-columns: repeat(3, minmax(1fr, 300px)); }
不幸的是,像上面这样看似简单,其实是不行的。若是max小于min的话,css会被忽略。在minmax()
中fr
不能使用。实际上实现这个需求很容易,在grid-template-columns
或 grid-template-rows
中使用auto
,这样item就能够随着内容增大而变大了。 See the Pen The value of auto vs fr by CSS GRID (@cssgrid) on CodePen.
咱们能够设置一个 max-width
:
.grid { display: grid; grid-template-columns: repeat(3, auto); } .item { max-width: 300px; }
See the Pen The limits of minmax by CSS GRID (@cssgrid) on CodePen.
minmax()
的运行方式和使用我尚未彻底想出来,虽然如此,我仍是写了一篇文章(译者注:Medium entitled是什么我没有理解清楚,原文:I wrote an entire post on Medium entitled) The One Thing I Hate About Grid.
有多种办法供你选择,若是你就想多写点,你能够给多行设置多个名字。
.grid { grid-template-columns: [col1-start] 1fr [col1-end col2-start] 1fr [col2-end]; }
最简单的命名约定使用网格自动编号。不是去写 [col2],而是写为col 2
.griditem1 { grid-column-start: col 2; }
和span
关键字组合使用,咱们就不用去写column-start和column-end中的各类网格线数字了,这样能直观许多。
.grid { grid-template-columns: repeat(4, [col] 100px); } .griditem1 { grid-column: col 2 / span 2; }
想象一下一行上四等列这种布局,使用百分比是多么的容易grid-template-columns: 25% 25% 25% 25%
。
可是当想用grid-gap
属性的时候那?若是设置grid-gap: 10px
,那么这一行上将有三个空隙,每一个10px,总体的宽度就是100% + 30px,大于100%滚动条就出来了。虽然能够经过计算来解决,可是若是使用fr,这太容易了grid-template-columns: 1fr 1fr 1fr 1fr
See the Pen fr unit vs percentage by CSS GRID (@cssgrid) on CodePen.
没有办法强制自动布局算法留下一些行和列是空的。
grid-gap
可让咱们设置内容间的距离。grid-row-gap
和grid-column-gap
能设置行或列之间的间隙,但是若是我想让第一行和第二行相距10px,第二行和第三行相距50px,用现有的网格是无法实现的,除非建个空行占位。
你可能见到过像下面这样写grid-template-area
的::
grid-template-rows: "header header header" "main main main" " . . ." "secondary secondary secondary" "footer footer footer";
应该提供一个比较聪明的办法,让布局算法去作这件事。不幸的是,这样写也没用。此语法简单地表示,咱们不想将第三行变成一个命名的网格区域。但是grid-template-rows将仍然在那结束。
12列网格算是web design的默认配置了。Bootstrap引导你们用12列网格,致使不少框架都是12列网格。12既能被3整除也能被4整除,能让咱们有更多种布局摆放方式。1行12列,1行6列,1行4列,1行3列,1行2列
虽然有些人喜欢每个项目老是使用相同的网格,可是你应该去思考你真正须要的,有时候没有必要有更多的列,你应该创建一个网格,对针对你的内容去布局,而不是一个12列网格处处用。
看看这个例子 Gridset. Gridset是一个制做网格很是有用的工具, 可是原生CSS的网格不须要你使用任何工具,可是能够看看它展现的一些良好的网格设计。
看看我写的例子,CSS原生网格是多么的自由啊:
See the Pen text layout with CSS Grid module by CSS GRID (@cssgrid) on CodePen.