最近挺忙的,准备考试,还有其他的事,没时间研究东西,快周末了,难得学点东西,grid是之前看到的,很好奇,讲的二维的布局,看起来很方便,应该很适合移动端布局,所以今天抽时间学一学,这个当是笔记了。参考的是阮老师的博客和HTML中文网的文章。
阮一峰:CSS Grid 网格布局教程
http://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html
CSS Grid 布局示例大全
https://www.html.cn/archives/8635
不系统的解释了,系统的看阮老师的博客,我再复述一遍没屁用,然后再看布局示例大全,然后就能懂个八九不离十了。但是我途中遇到一些问题,我这篇是总结一下我遇到的问题,顺便和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;
}
圣杯布局:
Header
Article
关于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。