Css权威指南(4th,第四版中文翻译)-13.Grid布局

其实在CSS早期,布局这块一直是个空白,只能通过类似于Float,clear等hack技术来完成布局。到后面flexble box的出现极大扩展了布局的功能,但是flex更适合于细节的布局,例如导航栏,而全局的布局知道Grid出现才有了较大的进步。


创建一个Grid容器

创建grid的第一步就是定义一个grid的容器(container),类似于定位中的容器盒子。grid分为两类:普通的regular grid和inline grid。跟flex一样,都需要在容器元素的display属性值进行申明:


image.png

虽然grid在很多时候和block很类似,不过他们也有以下的区别:

  1. 浮动元素在grid容器中无效:


    image.png
  2. grid容器的margin并不会与子代的margin合并


    image.png

同时也有一些CSS属性是对grid元素无效的:

  • 所有的column属性
  • ::first-line ::first-letter
  • float, clear
  • vertical-align

基本的Grid术语

基本的元素名称汇总如下:


image
  • grid track: 其实是横向和纵向的长度;
  • grid cell:是由4条网格线(grid line)所包围的最小区域;
  • grid area:网格区域就是有网格线包围的区域,可能有一个或多个cell组成。

放置Grid Lines

放置grid line还是比较复杂的,来看下下面这两个属性:


image.png

首先我们来试试创建固定宽度的格点:

#grid {display: grid; grid-template-columns: 200px 50% 100px;}
image.png

而且有意思的是,你开可以为你的grid line设置名称,放到[]里面就可以:

#grid {display: grid; grid-template-columns:
            [start col-a] 200px [col-b] 50% [col-c] 100px [stop end last];
        }
image.png

row方向的配置和column是一致的:

#grid {display: grid; grid-template-columns:
[start col-a] 200px [col-b] 50% [col-c] 100px [stop end last]; grid-template-rows:
            [start masthead] 3em [content] 80% [footer] 2em [stop end];
        }
image.png

有时候我们想要区间的范围设定一个范围而不是个具体的值,那么就可以借助minmax来实现:

#grid {display: grid; grid-template-columns:
[start col-a] 200px [col-b] 50% [col-c] 100px [stop end last]; grid-template-rows:
            [start masthead] 3em [content] minmax(3em,100%) [footer] 2em [stop end];
        }

image.png

另外还可以借助calc来做计算,如果要计算剩余范围的话:

grid-template-rows:
[start masthead] 3em [content] calc(100%-5em) [footer] 2em [stop end];

flexible grid 轨迹

之前我们看到的都是定死的grid配置,那么现在来看看grid的弹性配置。我们用的单位比较特别,称为分数单位(Fractional units),简称为fr。

grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-columns: 25% 25% 25% 25%;

上面两个操作其实效果是一样的:


image.png

grid 适配内容大小

除了上面的弹性布局,其实CSS还提供了针对内容的适配,有min-conten, max-content还有fit-content。

#g1 {display: grid;
grid-template-columns: max-content max-content max-content max-content; }
#g2 {display: grid;
grid-template-columns: minmax(0,max-content) minmax(0,max-content)
              minmax(0,max-content) minmax(0,max-content);
        }

image.png
#grid {display: grid; grid-template-columns: 1fr fit-content(150px) 2fr;}
#grid2 {display: grid; grid-template-columns: 2fr fit-content(50%) 1fr;}

fit-content(argument) => min(max-content, max(min-content, argument))

#thefollowing { display: grid;
grid-template-columns:
fit-content(50ch) fit-content(50ch) fit-content(50ch);
font-family: monospace;}

image.png

重复格线

想要实现重复的格线,利用repeat函数会更加方便,比如要产生10个5em宽度的区域就可以写成:

#grid {display: grid; grid-template-columns: repeat(10, 5em);}

而且repeat的后面参数是可以持续添加的,比如:

#grid {display: grid;
grid-template-columns: repeat(3, 2em 1fr 1fr);}
image.png

Grid 区域

image.png

网格区域是用来标志区域的,来看下:

#grid {display: grid; grid-template-areas:
            "h h h h"
            "l c c r"
            "l f f f";}
image.png

可以是更形象的:

#grid {display: grid; grid-template-areas:
            "header     header    header    header"
            "leftside   content   content   rightside"
            "leftside   footer    footer    footer";}

将元素添加到Grid

之前我们都是在讲怎么定义grid,现在讲讲怎么把元素放到grid里面。

使用column和row线

image.png
.grid {display: grid; width: 50em; grid-template-rows: repeat(5, 5em); grid-template-columns: repeat(10, 5em);}
.one {
grid-row-start: 2; grid-row-end: 4; grid-column-start: 2; grid-column-end: 4;}
.two {
grid-row-start: 1; grid-row-end: 3; grid-column-start: 5; grid-column-end: 10;}
.three {
grid-row-start: 4; grid-column-start: 6;}

这个通过设置row和column两个方向的起点和终点来规定元素在grid所占用的位置。


也可以用span来标识要跨几个格点:

#grid {display: grid;
grid-template-rows: repeat(5, 5em); grid-template-columns: repeat(10, 5em);}
.one {
grid-row-start: 2; grid-row-end: span 2; grid-column-start: 2; grid-column-end: span 2;}
.two {
grid-row-start: 1; grid-row-end: span 2; grid-column-start: 5; grid-column-end: span 5;}
.three {
grid-row-start: 4; grid-row-end: span 1; grid-column-start: 6; grid-column-end: span;}

row和column的简写

image.png

这两个属性极大简化了选择的操作,来看例子:

#grid {display: grid;
grid-template-rows: repeat(10, [R] 1.5em);
grid-template-columns: 2em repeat(5, [col-A] 5em [col-B] 5em) 2em;}
.one {
grid-row: R 3 / 7; grid-column: col-B / span 2;}
.two {
grid-row: R / span R 2;
grid-column: col-A 3 / span 2 col-A;}
.three { grid-row: 9;
grid-column: col-A -2;}
#grid {display: grid; grid-template-areas:
            "header header"
            "sidebar content"
            "footer footer";
grid-template-rows: auto 1fr auto;
grid-template-columns: 25% 75%;}
#header {grid-row: header / header; grid-column: header;}
#footer {grid-row: footer; grid-column: footer-start / footer-end;}
image.png

同时也可以通过area的名称来做范围的选择:


#grid {display: grid; grid-template-areas:
            "header header"
            "sidebar content"
            "footer footer";
grid-template-rows: auto 1fr auto;
grid-template-columns: 25% 75%;}
#header {grid-row: header / header; grid-column: header;}
#footer {grid-row: footer; grid-column: footer-start / footer-end;}
image.png

使用区域

image.png

借助grid-area可以直接让元素绑定之前定义好的区域:


#grid {display: grid; grid-template-areas:
            "header     header    header    header"
            "leftside   content   content   rightside"
            "leftside   footer    footer    footer";}
#masthead {grid-area: header;} #sidebar {grid-area: leftside;} #main {grid-area: content;} #navbar {grid-area: rightside;} #footer {grid-area: footer;}
<div id="grid">
<div id="masthead">...</div> <div id="main">...</div> <div id="navbar">...</div> <div id="sidebar">...</div> <div id="footer">...</div>
</div>
image.png

Grid Flow

之前我们讲到的是用户自己定义grid元素位置的情况,那么如果不指定的话有没有自动填充的方式么?答案是有的,就是使用grid-auto-flow


image.png
<ol id="grid"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ol>
#grid {display: grid; width: 45em; height: 8em; grid-auto-flow: row;}
#grid li {grid-row: auto; grid-column: auto;}
image.png

grid 简写

image.png
grid:
"header header header header" 3em ". content sidebar ." 1fr
"footer footer footer footer" 5em / 2em 3fr minmax(10em,1fr) 2em;
grid-template-areas:
"header header header header" ". content sidebar ."
"footer footer footer footer";
grid-template-rows: 3em 1fr 5em; grid-template-columns: 2em 3fr minmax(10em,1fr) 2em;

打开Grid间的空隙

之前我们所有的grid都是紧挨着的,接下来我们来看下如何在其中添加空白。


image.png
#grid {display: grid; 
grid-template-rows: 5em 5em;
grid-template-columns: 15% 1fr 1fr; 
grid-column-gap: 1em;}
image.png

另外一个添加gap的属性是:


image.png
#grid {display: grid; grid-template-rows: 5em 5em; grid-template-columns: 15% 1fr 1fr; grid-gap: 12px 2em;}

image.png

Grid对齐

grid 元素的对齐和flexbox其实是很像的,来看下对照表:


image.png
#grid {display: grid;
align-items: center; justify-items: center;}
image.png

图层及其排序

grid元素支持重叠,例如:

#grid {display: grid; width: 80%; height: 20em;
grid-rows: repeat(10, 1fr); grid-columns: repeat(10, 1fr);}
.box01 {grid-row: 1 / span 4; grid-column: 1 / span 4;} .box02 {grid-row: 4 / span 4; grid-column: 4 / span 4;} .box03 {grid-row: 7 / span 4; grid-column: 7 / span 4;} .box04 {grid-row: 4 / span 7; grid-column: 3 / span 2;} .box05 {grid-row: 2 / span 3; grid-column: 4 / span 5;}
image.png

所以可以通过设置z-index来调整图层的前后顺序:


image.png

另一种方式的排序就是使用order属性:

.box02 {order: 10;}
image.png

小结

grid布局还是比较复杂的,不过功能也非常强大。作者自己有时候也被搞晕了,但还是希望能够克服这些,因为你付出的耐心和坚持的回报会是巨大的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 简介CSS网格布局(又称“网格”),是一种二维网格布局系统。CSS在处理网页布局方面一直做的不是很好。一开始我们用...
    _leonlee阅读 64,997评论 25 173
  • 上一篇,介绍了grid的浏览器兼容和重要的几个概念,接下来继续介绍grid的容器属性。 Grid(网格) 属性目录...
    codeTao阅读 2,054评论 0 1
  • 简介 CSS Grid布局 (又名"网格"),是一个基于二维网格布局的系统,旨在改变我们基于网格设计的用户界面方式...
    咕咚咚bells阅读 2,494评论 0 4
  • 前言 之前写过一篇关于flex的布局,但是发现很多的问题,flex布局虽然可以解决,但是解决起来比较复杂,究其本质...
    kim_jin阅读 860评论 2 3
  • 为什么不结婚,因为没有遇到感觉对的人;为什么离婚,因为没有感觉了;为什么出轨,因为我想要那样的感觉。 感觉是什么...
    一个人飘零阅读 201评论 0 1