果冻公开课第十一课:CSS强大的布局系统 Grid
CSS的布局方式,一直以来都不够完善,无论是table,还是float,还是position或者是inline-block,都更像是在残缺不全的设计基础上的hack方式。
flex已经在某种程度上对布局有所改变,但是只解决了一维布局的问题。
那么有没有更好的方式,来跳出原本CSS布局的限制,用更简单和容易理解的方式完成复杂的布局呢?
文字解析:
CSS的布局本质上是从上到下,从左到右的书写顺序,以现在的角度来看,这种布局的理念并未考虑到整体,也很难去实现居中,对齐,分布等。
布局的本质到底是什么?怎么去安排元素占据的空间、顺序,可否从别的领域中学习新的布局方式呢?
周星驰有一部电影,叫做《大内密探零零发》,其中一段关于骚阳阳的情节是这样的:
把一个平面,分成网格,横向和竖向两种轴向完美切割平面,就可以很精准的确定某块区域。这和我们的经纬度是不是也很相似?中国象棋和围棋的棋谱也是这种思路啊。
所以一个大胆的设想就是,能否把网页切分,变成无数小格子,像我们小时候的作业本一样,然后,定位和布局的时候,直接指定一个元素在第几格,占据多少行多少列。
我们按照这种思路走下去,要切分网格,首先要告诉浏览器,接下来的布局是新一代的网格布局方式。好在display可以约定设置一个新的值来处理:grid
.container {
display: grid;
}
如果是内联,我们就用inline-grid
.container {
display: inline-grid;
}
既然要画格子,每一条线的间距是默认,还是交给前端去自由设置?考虑到布局的多样性,干脆提供一种自由设置网格的方式:
.container {
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}
通过新增加的两个属性,grid-template-column和grid-template-rows,我们可以让前端自由在容器内切分空间了,是不是很开心?
emm,如果有小调皮想要说,要是线太多会数错怎么办?
满足你!可以让你任意指定每一条线的名字!
.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];
}
额,你觉得这样的线要是多重复几遍会超级麻烦。。。?好的吧,懒毕竟是程序员的第一推动力,那我们再增加一种语法糖,简洁地描述一下:
.container {
grid-template-columns: repeat(2, 100px 20px);
}
怎么样,是不是完美的支持你在容器里画各种横线竖线了。不过第二个问题又来了,线画好之后,又该怎么去布置元素呢?
怎么布置元素
这种如果太复杂,就用起止位置来代替
起止位置来代替
这样相当于拿起画笔,可以随意指定网格中的元素占据位置。
格子画好了,定位和占位也有了,开心!
等等,好像还没完事儿,对齐怎么处理??
emmm,对我们还忘记了,怎么对齐。
没格子之前,常用的对齐就是左 ,右对齐,上对齐,下对齐和居中对齐。有了网格之后,我们可以支持:
- 起始边缘对齐(例子)
container {
justify-items: start;
}
2.结束边缘对齐(例子)
container {
justify-items: end;
}
3.居中对齐(例子)
.container {
justify-items: center;
}
4.填满单元格(例子)
.container {
justify-items: stretch;
}
除了行上对齐外,还能指定列上的对齐,同样是
- 起始边缘对齐(例子)
.container {
align-items: start;
}
2.结束边缘对齐(例子)
.container {
align-items: end;
}
3.居中对齐(例子)
.container {
align-items: center;
}
4.填满单元格(例子)
.container {
align-items: stretch;
}
除了指定网格内所有元素的对齐外,还能单独指定某一个元素的对齐:
单个元素的行对齐也是四种方式,
- 起始边缘对齐(例子)
.item-a {
justify-self: start;
}
2.结束边缘对齐(例子)
.item-a {
justify-self: end;
}
3.居中对齐(例子)
.item-a {
justify-self: center;
}
4.填满单元格(例子)
.item-a {
justify-self: stretch;
}
单个元素的列对齐同样是四种方式,
- 起始边缘对齐(例子)
.item-a {
align-self: start;
}
2.结束边缘对齐(例子)
.item-a {
align-self: end;
}
3.居中对齐(例子)
.item-a {
align-self: center;
}
4.填满单元格(例子)
.item-a {
align-self: stretch;
}
对齐也搞定了,好像还差点什么??
emmm看起来有点满,元素之间还少了点间隙,怎么设置间隙呢?
没格子之前我们都是用margin,现在有网格线了,可以直接设置网格线的粗细大小,也就等同于元素之间的间隙。
设置元素间隙
这样,先画出来格子,再定位元素和占据的空间,最后指定布局方式,是不是就可以在我们的世界里为所欲为了?
我们来看几种常见的布局:
一、左右固定中间自适应
以前,这需要使用margin,float, position 解决,圣杯布局是一个比较好的解决方案。grid 布局相比过去的方式简单许多,只需要在 container 上设置 grid-template-columns: 100px auto 100px。
.container {
display: grid;
grid-template-columns: 100px auto 200px;
}
二、复杂布局
如果说前一种布局还能用flex解决,而这种复杂布局就有些困难了。grid布局可以在 container 上使用 grid-template-areas,在 item 上设置 grid-area 属性来设置。
复杂布局设置
嗯,有没有觉得之前的布局太复杂了?现在我们给我们伟大的创意起个名字吧,我们把它叫做:Grid
既然方案有了,前端er就像是设计师,可以遵循这种方案来完成代码。各大浏览器厂商就需要遵守这种设计规范来实现它,好在现在大多数浏览器都支持了grid,所以你可以开心的使用grid的来完成成布局了。(展示出来支持浏览器最低版本)
甩开过去的束缚才能创造新世界,你有没有比网格布局更好的布局方案?