曾经在视频网站看过国外的关于css grid layout演讲,一看视频时长就关了。。。后来在一个项目里用了一下,发现其实要简单使用起来没有那么多名堂。
试想一下这个场景:当页面左侧有一个只有window高度一样高的菜单,而右侧的主要内容却高过这个菜单,我们无法得知右侧内容的高度来写给菜单,却要保证左侧菜单和右侧内容一样高(通常是为了background-color),如果强行用float解决了之后,有另一个同样的页面右侧内容比菜单要矮,是不是可能又要重写样式了?
以这个为目标写一个简单的html框架
headsidecontentfoot
开始第一行CSS代码
.grid{ display:grid; }
或者
.grid{ display:inline-grid; }
这样.grid容器内的直属子容器,将会以网格的形式存在。写了inline会自动宽高,不写则宽度撑满父容器。
.grid{ display:grid; grid-template-columns:1fr 1fr; grid-template-rows:1fr 2fr 1fr; }
rows的参数决定了有几行,columns的参数决定了有几列,一个fragment会占用一份空间。由于我的目标一行最多就只有两列,columns我只写两个就足够了,最终menu和content会平均分配父容器的宽度,而一列最多会有三个容器,head,foot都要占一整行,只给一个fr,而content的menu会比较高,给它2fr,这样高度就被分成了4份,每一份的高度从总高度里平均分配,注意这里的参数可以支持px,%, em,等等。
接下来给每一个grid定义一个名称
.head{ grid-area:head; } .side{ grid-area:side; } .content{ grid-area:content; } .foot{ grid-area:foot; }
给每个grid定义了一个标签之后,就可以在父容器中规划排序了。
.grid{ display:grid; grid-template-columns:1fr 1fr; grid-template-rows:1fr 2fr 1fr; grid-template-areas: //新增 "head head" //第一行全部是head,撑满整个宽度 "side content" //第二行左侧是side,右侧content "foot foot" //第三行全是foot,撑满整个宽度 }
好了,基本搞定了。接下来就是优化尺寸。因为side的宽度通常会固定,content自由变化,所以我们只要给side定义一个宽,让side所在的grid的宽度自动就可以了。
.side{ width:200px; } .grid{ display:grid; grid-template-columns:auto 1fr; grid-template-rows:1fr 2fr 1fr; grid-template-areas: "head head" "side content" "foot foot" }
好了,获得基础任务成就。
以下是延伸阅读:
Gap:
有时候grid之间需要一个相等的空白空间。一句话解决。
.grid{ display:grid; grid-gap: 10px; //同样支持em,%等 grid-template-columns:1fr 1fr; grid-template-rows:1fr 2fr 1fr; grid-template-areas: //新增 "head head" "side content" "foot foot" }
我开始很疑惑,这种需求,flexbox似乎也可以实现,但是如下图,一旦有一些较为复杂的需求,可能flex会比较麻烦,而grid就显得方便许多。。。
.grid{ display:grid; grid-gap: 10px; //同样支持em,%等 grid-template-columns:1fr 1fr; grid-template-rows:1fr 1fr 1fr 1fr; grid-template-areas: "head content" "head content" "side content" "foot foot" }
浏览器兼容:
IE下由于不支持grid-template-areas, 所以考虑兼容的时候以上用法就失效了,每个div都要单独声明自己占用了几块。
虽然caniuse上说IE10,11,只需要加前缀-ms-,但是实际上我试了下,这样是完全行不通的。
.grid{ display:-ms-grid; display:grid; -ms-grid-rows: 1fr 1fr; grid-template-rows: 1fr 1fr; -ms-grid-columns: 1fr 2fr 1fr; grid-template-columns: 1fr 2fr 1fr; grid-template-areas: "head head" "side content" "foot foot" } .head{ -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-row-span: 1; grid-area:head; } .side{ -ms-grid-column: 2; -ms-grid-row: 1; grid-area:side; } .content{ -ms-grid-column: 2; -ms-grid-row: 2; grid-area:content; } .foot{ -ms-grid-column: 3; -ms-grid-row: 1; -ms-grid-row-span: 1; grid-area:foot; }
好像没有办法测试,但是应该是这样没错。