本文摘自:please call me HRcss
so,first question? 啥是 grid 布局?
grid 布局是针对 Web 布局的一个升级版,首先,回想一下,咱们写 HTML 的时候,一个一个 div 像搭积木同样,完成咱们最后的网页。固然,咱们还须要使用 CSS 来配置咱们每一个 DOM 元素的具体位置,好比 navbar,sidebar 等等。有时候还要用各类 trick 才能知足咱们想要的布局结果。但为啥总感受不爽... 我就只想要这个元素放到指定位置而已,有这么难吗?web
有的面试
固然,你可使用 absolute 来完成,但这样形成的性能损耗我就很少说了,问题是,你调位置估计就要哭在哪。。。为啥? 太复杂了。。。按照图形学来讲,若是有一个坐标让我布局,那就行了。 so, grid 就这样诞生了。经历了 flexbox 的一维布局,grid 咱们就能够用一句话表达:算法
grid 是网页的二维布局方式chrome
ok, let's start。因为 grid 的支持性真的很渣。。。因此使用时须要额外开启实验室特性,在 Chrome 中,打开 chrome://flags 开启实验特性便可。首先,咱们来了解一下关于 grid 的基本概念。ide
grid 的内容其实和 table,flexbox 差很少。至关于二者的结合产物。一般,直接经过 display:grid;
来使用。最最基本的格式为:函数
<div class="container" style="display:grid;"> <div class="item item-1"></div> <div class="item item-2"></div> <div class="item item-3"></div> </div>
这里就包含了两个最基本的概念。布局
container 就是使用 display:grid
的 DOM。items 就是 container 包裹的一级子元素。记住:二级子元素就和 grid 不要紧!
而后,剩下的就是和 table 相似的属性了。性能
这个就比较好解释了,先看图吧:测试
这是 grid_line
这是 grid_cell
固然,还没完,接着就是 repeat cell 事后的理念。
track 至关于就是 行或者列。area 就是多个 cell 组成的面积。
这是 track
这是 area
grid 的强大之处在于,他能够将网页划分为不少小格子,而你能够将你的 DOM 随意的放在你想放的格子里面。还有一个必需要记住的点:
column, float, clear, 和 vertical-align 在 grid 布局中是没有效果的!
咱们先来看个 demo:
请问,你能在 5min 以内实现下列布局吗?
word哥。。。在没有接触到 grid 以前,我最早想到的就是使用 flexbox 来实现。并且须要 8 个 div。并且尼玛就 5min。要是遇到这样的面试题,我估计就直接喷面试官了。。。MDZZ。 但,面试官总会显现他蜜汁微笑说,这,不,是,很,简,单,吗?
是的,使用 grid 布局,真的很简单。看下实际代码也就几行:
// HTML <div id="container"> <div class="column-1">one</div> <div class="column-2">two</div> <div class="column-3">three</div> <div class="column-4">four</div> <div class="column-5">five</div> </div> // CSS 部分 body { min-width: 550px; } #container{ height: 200px; display: grid; grid-template-columns:1fr 1fr 1fr 1fr; grid-template-rows:1fr 1fr 1fr; grid-template-areas:"one one two three" "four four two three" "five five five three"; } .column-1{ grid-area:one; background-color: #F8594C; } .column-2{ grid-area:two; background-color: #FFA29B; } .column-3{ grid-area:three; background-color: #318B98; } .column-4{ grid-area:four; background-color: #E73123; } .column-5{ grid-area:five; background-color: #ABE646; }
完整的实例能够参考: grid 布局
能够说,grid 就是让你用张纸画几个网格,而后填充,而后网页就作好了。若是你想要动效的话,使用 animation 就 ok。啊~ 真简单。。。 接下来,咱们来详细的看一下 grid 里面有哪些属性标签。权威指南请参考: MDN grid layout
grid 的标签能够细分为两类:一类是属于 container,一类是数据 items。
各有:
container:
grid-template-columns
grid-template-rows
grid-template-areas
grid-template
grid-auto-columns
grid-auto-rows
grid-auto-flow
grid
grid-column-gap
grid-row-gap
grid-gap
justify-items
align-items
justify-content
align-content
items:
grid-column-start
grid-column-end
grid-row-start
grid-row-end
grid-column
grid-row
grid-area
justify-self
align-self
看起来蛮多的,不过细分下来就几个: template,auto,gap,布局(content/items)
这里,咱们就按上面的分类来说解。首先是 container 分类部分:
container 中的 template 有三种(还有一个是综合标签):columns,rows,areas。咱们先来看下 columns 和 rows。
grid-template-columns/rows
基本格式为:
grid-template-columns: <track-size> ... | <line-name> <track-size> ... | subgrid; grid-template-rows: <track-size> ... | <line-name> <track-size> ... | subgrid;
也就是说,该标签中属性仍是蛮多的。咱们简单介绍一下:
track-size:不管是 column 仍是 row,都是用来定义行高/列宽。取值能够为 px,%,auto,fr。重点说一下 auto 和 fr。 auto 和 其余两个属性结合起来才有效,表示自动充满剩下的空间。 fr 就是 free space 的意思,用来表示是否均分剩下的空间。
line-name:用来设置行/列 line 的名称。这个结合 item 中的 grid-row 有效。不设置的话,默认为 1,2,3,4...
subgrid:嵌套 grid 时有效。暂不在讨论的范围以内。
看实例吧:
设置以下属性值:
.container{ grid-template-columns: 40px 50px auto 50px 40px; grid-template-rows: 25% 100px auto; }
能够获得:
至关于每一个值都表明行/列宽,百分数的值相对于 container 的宽度来的。继续,咱们加上 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]; }
感受定义了 line-name 以后,会有点复杂。咱们能够这样记忆,值抽象为就是行/列,左右两侧就是线。这样感受是否是好一点了?
fr 的话,就比较简单了,均分操做:
.container{ grid-template-columns: 1fr 1fr 1fr; }
另外, css 还提供了一个 repeat 函数,来帮助咱们快速书写一样格式的样式:
// 使用 repeat grid-template-columns: repeat(3, 20px [col-start]) 5%; // 等同于 grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
另外,咱们还可使用简写形式,将 columns 和 rows 写在一块儿。
// 基本格式就是: row / column / area grid-template:repeat(4,1fr) / repeat(3,1fr);
接下来是 grid-template-areas
。该属性一般和 items 中的 grid-area
结合一块儿使用。
grid-template-areas
他的基本格式为:
grid-template-areas: "<grid-area-name> | . | none | ..." "..."
记住,areas 写的时候,注意是能够分行写的,这点极其重要。由于这能够对应于每一个网格的 name 。基本取值为:
grid-area-name:至关于给每一个 cell 取名字,好比 header,footer,body 等等。
. : 将该单元格设置空值。就是啥也没有的意思。连名字也没有,那么就至关于将该 cell 设为 empty。
none:是真的啥也没有,当和 grid_name 混合使用时,和 .
没啥太大的区别。但关键在于,他一般用于单独定义的。
记住,该属性必须和 item 中的 grid-area
才有效果,具体的使用就是我上面的 demo:
#container{ height: 200px; display: grid; grid-template-columns:1fr 1fr 1fr 1fr; grid-template-rows:1fr 1fr 1fr; grid-template-areas:"one one two three" "four four two three" "five five five three"; } .column-1{ grid-area:one; background-color: #F8594C; } .column-2{ grid-area:two; background-color: #FFA29B; } ...
总体效果如: grid-template-area
grid 中 gap 相关的有两个:grid-column-gap,grid-row-gap。这很好理解,就是用来设置行/列间隙。基本格式也是很简单:
grid-column-gap: <line-size>; grid-row-gap: <line-size>;
line-size:基本 web 中的长度单位均可以使用,好比 px,vh,em,rem,auto 等等。不过比较遗憾的是,他不能设置每个行/列间隔的大小。
好比:
.container{ grid-column-gap: 10px; grid-row-gap: 15px; }
另外还有一个综合单位就是: grid-gap。它其实就是上面两个的综合。基本形式为:
grid-gap: <grid-column-gap> <grid-row-gap>;
接下来咱们来看一下 auto 系列。
auto 包含的内容和 gap 差异不大,不过,他包含的是 3 个 tag:
grid-auto-columns: <track-size> ...; grid-auto-rows: <track-size> ...; grid-auto-flow: row | column | row dense | column dense
咱们先说一下前两个: grid-auto-columns,grid-auto-rows
这两个属性,主要是用来弥补当元素放的位置超出 grid 时,在外部虚拟生成行/列的大小值。感受有点难懂。。。这个的主要应用场景一样须要和 item 中的两个属性值:grid-column,grid-row 结合使用。这两个是干吗的?他们是根据网格的线来设置元素的位置。
好比:
// 这个 container 只有 2x2 的布局结构 .container{ grid-template-columns: 60px 60px; grid-template-rows: 90px 90px }
想这样:
如今将一个 item-b 放到 2x5 的右下角位置上。即为这样:
而后设置 grid-column 和 grid-row 能够为:
grid-column: 5 / 6; // 第 5 条到第 6 条竖线之间 grid-row: 2 / 3; // 第 2 条到第 3 条横线之间
但这样的问题是,他虽然确实占了,可是那个 cell 是 0x0 的,至关于没有。。。那有啥用。因此,为了更加灵活的设置, grid 推出的 auto 系列,就有用了。这里,咱们能够设置:
grid-auto-columns: 60px; // 为啥不设 row? // 由于根本就没超过 row 的范围。。。
ok,如今就变为一下的格式:
固然,若是你设置超出了 row 的话,那就适合 grid-auto-rows 便可。如今看一个比较拗口的属性:
grid-auto-flow
它主要是用来设置多余元素在剩下位置的排列顺序,重置排序。基本格式为:
// row 为默认值 grid-auto-flow: row | column | row dense | column dense
row:设置剩下的元素按照行顺序一次填充,若是超出,自动增长行。
column:设置剩下元素按照列顺序依次填充,若是超出,自动增长列。
dense:强制剩下元素从第一个还未排的 cell 开始。
现假设,咱们有个 3x3 的布局:
初始样式为:
看一下 CSS:
// 这里设置的 3x3 布局。而后将第一个 item 放在第二个 cell 位置 #container{ height: 200px; display: grid; grid-template:repeat(3,1fr) / repeat(3,1fr); grid-auto-flow:row; } .column-1{ grid-column:2; background-color: #F8594C; } .column-2{ background-color: #FFA29B; } //...
而后,剩下的就会依次排开。Ok,如今咱们切换为 column,他排列方式就变为:
而后咱们再加上 dense
。最后的结果(column dense
)就变为:
感受,这个属性仍是挺复杂的,关键它的插入算法的机理并无太清楚,并且也还在草案道中,因此,咱们简单了解就好,不深究了。
最后就是 4 个定位布局的属性了。
justify-items
align-items
justify-content
align-content
items 相关是用来控制 cell 里面内容的分布位置和 flexbox 中的 align-items/justify-content 相似。
justify-items
justify-items 是用来控制 item 水平布局。基本格式为:
// stretch 是默认值 justify-items: start | end | center | stretch;
那它的实际效果是啥呢?
看几张图,估计就明白了。
justify-items: start;
效果为:
justify-items: center;
效果为:
剩下的 end 和 stretch 我就不赘述了。若是不是 stretch,它都是根据你元素中的文本内容进行自适应宽度的。 在 item 中使用 justify-self
能够控制独立 item 的布局位置。
align-items
align-items 就是用来控制 item 垂直布局。基本格式为:
// stretch 是默认值 align-items: start | end | center | stretch;
它的效果和 justify-items 很相似,一样看几个 demo:
align-items: start;
效果图为:
上下的我就很少说了。而且,在 item 中使用 align-self
能够控制独立 item 的布局位置。
剩下的还有两个:justify-content,align-content
content 相关
它俩作的工做差很少,和上述两个 tag 最大的区别在于,它们是用来控制整个 container 的布局。怎么说呢?
当使用 grid-template-rows/columns
设置行高/列宽时,若是所有使用的都是 px
并无填充满时,那么contaienr 就会有一个块空出来。因此,为了解决这个问题,grid 就提出了 justify-content,align-content 这两个 tag。
基本格式为:
// start 为默认值 justify-content: start | end | center | stretch | space-around | space-between | space-evenly; align-content: start | end | center | stretch | space-around | space-between | space-evenly;
这里,针对 justify-content 进行下讲解,另一个是类似的只是排列方向是按纵向来进行排列的。先假设,咱们经过 grid-template-columns
设置的 container 以下图:
分别添加属性测试:
justify-content: end;
放后
justify-content: center;
放前
justify-content: stretch;
拉伸
justify-content: space-around;
该属性的意思是,将多余的 space 均匀分给每个 grid-item(左右都有)。
space-around
justify-content: space-between;
该属性的意思是,将多余的 space 均匀的分在 grid-item 之间,不包括先后。
space-between
justify-content: space-evenly;
该属性的意思是,将多余的 sapce 均匀的分在 grid-item 之间,包括先后。
space-evenly
基本上关于 container 的标签就已经说完了。下面咱们来看看 items 相关(可少了。。。)
items 中的标签有 3 类:line,area,布局
在 grid 布局中,定位一个 DOM 的位置,有两种方式,一种是靠 grid-line,好比,指定你从哪一根开始,另一种是靠 area,好比,将一个 DOM 放在 1,2,3 cell 中。这里,关于 grid-line 布局的设置属性有两个:行/列
grid-column: grid-column-start / grid-column-end; grid-row:grid-row-start / grid-row-end;
里面基本的取值能够为:
<number> | <name> | span <number> | span <name> | auto
好比:
grid-column:1/3; // 将 DOM 放在 第一行到第三行之间。
number:指定第几根线,来决定放的位置。
name:根据 grid-template-columns 中命名的 grid-line-name
来决定放的位置。
span <number>/<name>:至关于到...为止。一般结合 number 时,效果才能体现出来,好比:1/span 2
。表示从第 1 根开始,到过 2 根线位置。最后就是 1/3
。
好比:
grid-column:1 / col4-start; grid-row: 2/span 2;
经过 area 布局的标签就一个:grid-area
基本格式为:
grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
name:根据 grid-template-areas 设置的 cell 的别名。好比:header,foooter 等。
row-start/.../column-end: 和上面的 grid-column 一致。用线来框出具体的范围。
例如:
grid-area: header; // 或者为: grid-area: 1 / col4-start / last-line / 6
在 container 中提到过,使用 justify-self,align-self 便可实如今 cell 中,content 的排列位置。经常使用取值为:
justify-self: start | end | center | stretch; align-self: start | end | center | stretch;
具体的实现方式在 container 中我已经说过了,这里就不赘述了。