grid布局笔记
最近挺忙的,准备考试,还有其他的事,没时间研究东西,快周末了,难得学点东西,grid是之前看到的,很好奇,讲的二维的布局,看起来很方便,应该很适合移动端布局,所以今天抽时间学一学,这个当是笔记了。参考的是阮老师的博客和html中文网的文章。
阮一峰:css grid 网格布局教程
css grid 布局示例大全
不系统的解释了,系统的看阮老师的博客,我再复述一遍没屁用,然后再看布局示例大全,然后就能懂个八九不离十了。但是我途中遇到一些问题,我这篇是总结一下我遇到的问题,顺便和flex做一下对比,方便以后回顾。
fr关键字:
grid-template-columns:150px 1fr 2fr
这个1fr 和 2fr和父容器宽度有关系,1fr 和2fr是会主动填补父容器宽度(类似flex里的basis属性),保证他们俩的宽度关系为1:2,但是他们和150px没有关系,150px始终为150px。
布局实例:
1.父容器中设置两个项目分别占七三比例
.wrapper { display: grid; grid-template-columns: 70% 30%; }
这个是一维的,只有一行,所以flex也能够布局出来。(简写啥的看不懂的话可以去看我有一篇flex布局笔记)
.wrapper{ display: flex; } .item1{ flex:70% } .item2{ flex:30% }
好像grid方便一点哈,那就接着往下看哈。
2.传统十二网格布局
可以直接在容器上定义一个
display: grid; grid-template-columns: repeat(12, 1fr);
就完事了。
flex布局虽然也是一维的,但是要分别定义容器还有项目
.warpper{ display:flex } //前提12个项目的class都为item .item{ flex:1 }
各有千秋吧,但是flex强项就是一维的,grid强项在于二维布局。我接着看看二维的布局
控制边距
flex没有控制边距的特殊属性,都是自动的,如果想要就是加margin.但是grid加了gap属性,可以column-gap也可以row-gap
指定区域,合并多块
.container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-template-areas: 'a b c' 'd e f' 'g h i'; }
上面这个是默认的情况,九个单元格各司其职。谁都不理谁。
但是可以可以将他们更换变成
grid-template-areas: 'a a a' 'b b b' 'c c c';
类似,如果将其中一块变成.
的话,那.
所属的区域傻东西都没有
表示没有用到该单元格,或者该单元格不属于任何区域
注意,区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为
区域名-start
,终止网格线自动命名为区域名-end
。比如,区域名为
header
,则起始位置的水平网格线和垂直网格线叫做header-start
,终止位置的水平网格线和垂直网格线叫做header-end
。
grid-auto-flow
跟flex的flow不一样,flow是wrap和nowrap还有wrap-reverse。而这个gird-auto-flow可以调整密度。
column dense
和row dense
可以自动填补竖向和横向的空白
剩下没啥东西了,记得东西偏多,感觉和flex差不多,都是比较方便的布局方式,多了二维操作和指定特殊的块儿的功能。
项目中应用
在项目中的布局主要是应用到下面这样的类似的效果。
.warpper{ display: grid; grid-gap: 5px; grid-template-columns: repeat(12, 1fr); grid-template-rows: 50px 350px 50px; grid-template-areas: "h h h h h h h h h h h h" "m m c c c c c c c c c c" "f f f f f f f f f f f f"; }
然后再在项目中指定相应的iteam为h,m,c,f
.header { grid-area: h; } .menu { grid-area: m; } .content { grid-area: c; } .footer { grid-area: f; }
圣杯布局:
<!doctype html> <html> <head> <title></title> </head> <body> <div class="grid"> <header>header</header> <aside class="siderbar-left">lefr sidebar</aside> <article>article</article> <aside class="sidebar-right">right sidebar</aside> <footer>footer</footer> </div> </body> <style type="text/css"> .grid{ display:grid; grid-template-rows: repeat(3,100px); grid-template-columns: 150px auto 150px; grid-gap:1em; } header, aside, article, footer { background: #eaeaea; padding: 1em; } header,footer{ grid-column: 1/4; } </style> </html>
关于span
sapn表示跨越,有些时候可以gird-column:1/span2
这样会让人感到困惑,我到底是跨越到哪去了,span2就是加两个,相当于gird-column:1/3
,其实占得部分就是1块儿和2块儿。
auto-fill的补充
.container { display: grid; grid-template-columns: repeat(auto-fill, 100px); }
我自己瞎看,于是乎走进了误区,因为总觉得这个gird-template-columns明明说设置列,但是为什么设计出来却是控制的行,我现在想明白了,就像上面这个例子,因为他要控制的是一个列的宽度,然后配合上auto-fill,我一列设置成100px,然后将这100px宽度的列自动填满整个行的宽度。直到写到这里我的困惑才被揭开,我服了。
关于fr的补充
fr是自动计算剩余地方的,比如说让
grid-template-columns:100px repeat(10,1fr)
这个解释一下就是,第一个列的宽度为100px,然后这十个把剩下的父容器宽度(一般grid布局的父容器都是body元素,所以会根据浏览器的宽度进行变化,方便进行响应式布局,以下父容器如果没有特殊标注的话一般都指的body元素)平均分了。
这个fr有几种情况:
- 1fr单独出现,会把父容器都占满
- n个1fr出现,这几个1fr会平均分父容器
- n个1fr,和一个2fr出现,会n+2的平均分,然后给1fr的一份,给2fr的两份。其他比例同理
自认为的难点
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr) )
这个破玩意困扰我很久,repeat的意思是前面是个数,后面是宽度,表示一种快速方便的写法。auto-fill是用列给这一行自动添加满元素,minmax是控制这个列的宽度最小为200px,最大为1fr。fr是上面讲过的。
可是最大为1fr ,1fr不是占满整个父容器宽度吗?,既然占满也就没有auto-fill的事儿了,一行一个不就完事了吗?
我开始陷入了这个误区好久,后来写了写demo才发现我的误区在于盲目的认为1fr会占整个宽度,但却忽略了几个1fr同时存在会平分的关系。也就是说,在父容器变化宽度的同时,我们的列会自动添加进来,比如说由399px变到了400px(现实情况一般会比400px大,因为默认会有边距)那么我们就会出现第二个列加入到同一行。但是在400px到600px这之间,我们列的最小宽度是200px,所以不会有新的列加入。那么剩下的宽度就会空着吗?
答案显然是不是的,因为我们设置了列的宽度,宽度为minmax这个范围,200px到1fr,1fr这时候的作用便显示出来了,因为比如说现在父容器宽度为500px,现在两个列存在这一行,都是1fr,所以这两个会把500px平均分,变成250px。