Grid布局

前言

之前写过一篇关于flex的布局,但是发现很多的问题,flex布局虽然可以解决,但是解决起来比较复杂,究其本质,还是flexbox(盒子布局)解决的问题是一维布局的问题,而不是二位布局的问题,那我们想要解决二维度布局的问题,就要用到我们今天将的Grid布局,也被称为网格布局。

基础概念

使用Grid布局其实是非常简单的,和使用Flex布局有一定的相似的地方,首先给容器(container)定义:dispaly:grid然后分歧的地方出现了,Grid布局需要设置列与grid-template-columns)和 行(grid-template-rows)的大小。然后在使用grid-columngrid-row属性来定义子元素的位置。Grid布局与Flex布局很类似,一开始项目的排序并不重要,可以将其放置在容器的任意位置、我们可以通过媒体查询来重新排列我们的项目。而且现在几乎大部分的主流浏览器都支持该布局,兼容性比较好。

重要的术语

1.网格容器(Grid Container)
我们对哪一个元素应用display:grid,谁就是网格容器,他是所有网格项的父元素。其中container就是网格元素。

<div class="container">
  <div class="item item-1"></div>
  <div class="item item-2"></div>
  <div class="item item-3"></div>
</div>

2.网格项(Grid Item)
网格元素的一级子元素就是网格项,下面的例子中sub-item是二级子元素,所以并不是网格项。

<div class="container">
  <div class="item"></div> 
  <div class="item">
    <p class="sub-item"></p>
  </div>
  <div class="item"></div>
</div>

3.网格线(grid line)
组成网格线的分界线。它们可以是列网格线(column grid lines),也可以是行网格线(row grid lines)并且居于行或列的任意一侧,下面黄色线就是列网格线。

网格线

4.网格轨道(Grid Track)
两个相邻的网格线之间为网格轨道。你可以认为它们是网格的列或行,下面在第二个和第三个网格线之间的黄色部分为网格轨道。

网格轨道

5.网格单元
两个相邻的行网格线和两个相邻的列网格线组成的部分就是一个网格单元,类似于Excel中的单元格,网格单元是最小的网格单元。

网格单元

6.网格区
网格区就是由任意数量的网格单元组成的区域,下面黄色部分就是一个网格区。

网格区

所有网格容器属性和网格元素属性

对于网格元素的相关属性:
display
grid-template-columns
grid-template-rows
grid-template-areas
grid-column-gap
grid-row-gap
grid-gap
justify-items
align-items
justify-content
align-content
grid-auto-columns
grid-auto-rows
grid-auto-flow
grid
现在让我们对所有的属性进行一一说明
display:grid | inline-grid | subgrid
grid:生成块级网格元素
inline-grid:生成行内网格
subgrid:如果网格容器本身就是一个网格项,那么这个属性用来获取父网格容器的列和行的大小。
ps:当元素设置为网格布局的时候,column 、float、clear、vertical-align属性是无效的。
grid-template-columns / grid-template-rows:<track-size> ... | <line-name> <track-size>
track-size:用来设置轨道的大小,可以来使用css的长度,百分比或是分数
line-name:网格线的名字,当然了,你可以选择任意的名字
说起来不是很理解,我现在举一个小栗子:

.container {
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}

实现的结果是:

track-size属性值的使用

那如果我们想给每一个网格线取名字的话,可以用下面的代码来实现:

.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];
}

实现的结果是:

name的使用

当然我们可以给每一个网格线,例如第二个网格线就可以有两个名字,分别是row1-endrow2-start

.container{
    display:grid;
    grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}

如果定义的包含重复的部分,我们可以使用repeat来进行简化

.container{
    display:grid;
    grid-template-columns: repeat(3, 20px [col-start]) 5%;
}

这段代码相当于下面的这段代码:

.container{
    display:grid;
    grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}

我们也可以使用fr将容器进行等分,例如下面就是将容器进行三等分,但是如果将fr于实际值一起使用,设置fr的行或是列会将剩余的部分进行等分。

.container{
    display:grid;
    grid-template-columns: 1fr 1fr 1fr;
     grid-template-rows: 1fr 1fr 1fr 20px;
}

grid-template-areas
通过获取网格项中的grid-area属性值(名称),来定义网格的模板。重复网格模板名称将跨越网格单元格。‘.’代表空网格单元。
grid-area-name: 网格项的grid-area属性值(名字)
‘.’ : 空网格单元
none: 不定义网格区域

.item-a{
  grid-area: header;
}
.item-b{
  grid-area: main;
}
.item-c{
  grid-area: sidebar;
}
.item-d{
  grid-area: footer;
}
.container{
    display:grid;
    grid-template-columns: 50px 50px 50px 50px;
    grid-template-rows: auto;
    grid-template-areas: "header header header header"
                         "main main . sidebar"
                         "footer footer footer footer"
}

结果样式:

grid-template-areas

grid-column-gap:<line-size>; 和 grid-row-gap: <line-size> ;
这两个属性是用来设置网格单元间距
line-size:网格线间距,设置单位值

.container{
    display:grid;
    grid-template-columns: 100px 50px 100px;
    grid-template-rows: 80px auto 80px; 
    grid-column-gap: 10px;
    grid-row-gap: 15px;
}

实现的结果是:

grid-column-row-gap

但是我们也看到了,间隔仅仅是作用域网格单元之间,并不作用在容器边缘。
grid-gap:<grid-row-gap> <grid-column-gap>;
这个属性是grid-row-gapgrid-column-gap两个属性的简写,但是如果仅仅设置一个值,那么grid-row-gapgrid-column-gap都是那个值。
justify-items: start | end | center | stretch ;
垂直于列网格线对齐,这个属性适用于网格容器中所有的网格项。
start: 顶部对齐。
end: 底部对齐。
center: 居中对齐。
stretch:填满(默认)。
下面我们对于上面的几个属性的值的样式仅仅一一验证。

.container{
    display:grid;
    justify-items: start;
}
grid-justify-items-start
.container{
    display:grid;
    justify-items: end;
}
grid-justify-items-end
.container{
    display:grid;
    justify-items: center;
}
grid-justify-items-center
.container{
    display:grid;
    justify-items: stretch;
}
grid-justify-items-stretch

align-items: start | end | center | stretch ;
垂直于行网格线对齐,适用于网格容器里的所有网格项。
start: 顶部对齐。
end: 底部对齐。
center: 居中对齐。
stretch:填满(默认)。
下面我们对于上面的几个属性的值的样式仅仅一一验证。

.container{
    display:grid;
    align-items: start;
}
grid-align-items-start
.container{
    display:grid;
    align-items: end;
}
grid-align-items-end
.container{
    display:grid;
    align-items: center;
}
grid-align-items-center
.container{
    display:grid;
    align-items: stretch;
}
grid-align-items-stretch

justify-content: start | end | center | stretch | space-around | space-between | space-evenly
如果我们用px非弹性单位定义的话,总的网格区域大小可能小于网格区域,这个时候可以设置网格的对齐方式。
start: 左对齐。
end: 右对齐。
center: 居中对齐。
stretch: 填满网格容器。
space-around: 网格项两边间距相等,网格项之间间隔是单侧的2倍。
space-between: 两边对齐,网格项之间间隔相等。
space-evenly: 网格项间隔相等。

.container{
    display:grid;
    justify-content: start;
}
grid-justify-content-start
.container{
    display:grid;
    justify-content: end;
}
grid-justify-content-end
.container{
    display:grid;
    justify-content: center;
}
grid-justify-content-center
.container{
    display:grid;
    justify-content: stretch;
}
grid-justify-content-stretch
.container{
    display:grid;
    justify-content: space-around;
}
grid-justify-content-space-around
.container{
    display:grid;
    justify-content: space-between;
}
grid-justify-content-space-between
.container{
    display:grid;
    justify-content: space-evenly;
}
grid-justify-content-space-evenly

align-content: start | end | center | stretch | space-around | space-between | space-evenly
如果用像px非弹性单位定义的话,总网格区域大小有可能小于网格容器,这时候你可以设置网格的对齐方式(垂直于行网格线对齐)。
start: 顶部对齐。
end: 底部对齐。
center: 居中对齐。
stretch: 填满网格容器。
space-around: 网格项两边间距相等,网格项之间间隔是单侧的2倍。
space-between: 两边对齐,网格项之间间隔相等。
space-evenly: 网格项间隔相等。

.container{
    display:grid;
    align-content: start; 
}
grid-align-content-start
.container{
    display:grid;
    align-content: end; 
}
grid-align-content-end
.container{
    display:grid;
    align-content: center; 
}
grid-align-content-center
.container{
    display:grid;
    align-content: stretch; 
}
grid-align-content-stretch
.container{
    display:grid;
    align-content: space-around; 
}
grid-align-content-space-around
.container{
    display:grid;
    align-content: space-between; 
}
grid-align-content-space-between
.container{
    display:grid;
    align-content: space-evenly; 
}
grid-align-content-space-evenly

grid-auto-columns: <track-size> ... ; 和 grid-auto-rows: <track-size>
自动生成隐式网格轨道(列和行),当你定位网格项超出网格容器范围时,将自动创建隐式网格轨道。
track-size: 网格轨道大小,可以是固定值,百分比或者是分数(fr单位)
我们首先先创建一个容器:

.container{
    display:grid;
    grid-template-columns: 60px 60px;
    grid-template-rows: 90px 90px
}

实现的效果是:

grid-auto

这是一个2X2的表格,我们但是我们现在使用grid-columngrid-row给网格进行定位

.item-a{
    grid-column: 1 / 2;
    grid-row: 2 / 3;
}
.item-b{
    grid-column: 5 / 6;
    grid-row: 2 / 3;
}
implicit-tracks

解释一下:grid-column: 1 / 2的1/2表示的是在第一条列网格线和第二条列网格选之间,但是我们看一下.item-b定位在第五根列网格线(column line 5 )和第六根列网格线(column line 6 )之间。但是我们现在的网格容器中并不存在这两条网格线,所以就会用两个0宽度来进行填充,在这里我们可以用网格自动行(grid-auto-rows)和网格自动列(grid-auto-columns)来定义这些隐式轨道宽度。

.container{
    display:grid;
    grid-auto-columns: 60px;
}

那么现在实现的结果就是这样的啦:

implicit-tracks

grid-auto-flow : row(默认) | column | dense
在没有设置网格项的位置时,这个属性控制网格项怎样排列。
row: 按照行依次从左到右排列。
column: 按照列依次从上到下排列。
dense: 按先后顺序排列

<section class="container">
    <div class="item-a">item-a</div>
    <div class="item-b">item-b</div>
    <div class="item-c">item-c</div>
    <div class="item-d">item-d</div>
    <div class="item-e">item-e</div>
</section>

下面定义5列2行网格,同时定义grid-auto-flow:row

.container{
    display: grid;
    grid-template-columns: 60px 60px 60px 60px 60px;
    grid-template-rows: 30px 30px;
    grid-auto-flow: row;
}

现在网格的布局是:

.item-a{
    grid-column: 1;
    grid-row: 1 / 3;
}
.item-e{
    grid-column: 5;
    grid-row: 1 / 3;
}

由于我们设置了grid-auto-flow:rowitem-bitem-citem-d在行上是从左到右排列,实现的结果如下:

grid-auto-flow-row

如果我们设置 grid-auto-flow: column;结果如下:

grid-auto-flow-column

grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [ / <grid-auto-columns>] ]
none: 设置为所有属性的默认值。
<grid-template-rows> / <grid-template-columns>: 设置行和列的值,其他属性为默认值。
<grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns>] ] : 设置网格自动流、网格自动行、网格自动列的值,其他未设置则为默认值。

.container{
    grid: 200px auto / 1fr auto 1fr;
}
等同于
.container{
    grid-template-rows: 200px auto;
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: none;
}
.container{
    grid: column 1fr / auto;
}
等同于
.container{
    grid-auto-flow: column;
    grid-auto-rows: 1fr;
    grid-auto-columns: auto;
}

设置在网格项上的属性

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end
  • grid-column
  • grid-row
  • grid-area
  • justify-self
  • align-self

grid-column-start: <number> | <name> | span <number> | span <name> | auto ;
grid-column-end: <number> | <name> | span <number> | span <name> | auto ;
grid-row-start: <number> | <name> | span <number> | span <name> | auto ;
grid-row-end: <number> | <name> | span <number> | span <name> | auto ;

通过网格线来定义网格项的位置。grid-column-startgrid-row-start定义网格项的开始位置,grid-column-endgrid-row-end定义网格项的结束位置。

line: 指定带编号或者名字的网格线。
span <number>: 跨越轨道的数量。
span <name>: 跨越轨道直到对应名字的网格线。
auto: 自动展示位置,默认跨度为1。

.item-a{
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start
  grid-row-end: 3
}
grid-start-end-a
.item-b{
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2
  grid-row-end: span 2
}
grid-start-end-b

ps:注:如果未声明grid-column-end或grid-row-end,默认将跨越一个轨道。项目也可以重叠,设置z-index来确定堆叠顺序。

grid-column: <start-line> / <end-line> | <start-line> / span <value> ;
grid-row: <start-line> / <end-line> | <start-line> / span <value> ;

grid-column-startgrid-column-endgrid-row-startgrid-row-end 的简写。

.item-c{
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}
grid-start-end-c

grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end> ;
定义网格项名字,以便创建模块(容器属性grid-template-areas来定义模块)。
name: 项目名子。
<row-start> / <column-start> / <row-end> / <column-end>: 可以是数字或网格线名字。
定义网格项名字:

.item-d{
  grid-area: header
}

通过网格线定位网格项:

.item-d{
  grid-area: 1 / col4-start / last-line / 6 ;
}
grid-start-end-d

justify-self: justify-self: start | end | center | stretch;
定义单个网格项垂直于列网格线的对齐方式。
start: 网格区域左对齐。
end: 网格区域右对齐。
center: 网格区域居中。
stretch: 网格区域填满。

.item-a{
  justify-self: start;
}
grid-justify-self-start
.item-a{
  justify-self: end;
}
grid-justify-self-end
.item-a{
  justify-self: center;
}
grid-justify-self-center
.item-a{
  justify-self: stretch;
}
grid-justify-self-stretch

ps:提示:也可以在容器上设置justify-items,达到全部网格项对齐。
align-self: start | end | center | stretch;
定义单个网格项垂直于行网格线的对齐方式。
start: 网格区域顶部对齐。
end: 网格区域底部对齐。
center: 网格区域居中。
stretch: 网格区域填满。

.item-a{
  align-self: start;
}
grid-align-self-start
.item-a{
  align-self: end;
}
grid-align-self-end
.item-a{
  align-self: center;
}
grid-align-self-center
.item-a{
  align-self: stretch;
}
grid-align-self-stretch

ps:也可以在容器上设置align-items,达到全部网格项对齐。

参考:Grid布局指南
来个小游戏放松一下

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

推荐阅读更多精彩内容

  • 简介CSS网格布局(又称“网格”),是一种二维网格布局系统。CSS在处理网页布局方面一直做的不是很好。一开始我们用...
    _leonlee阅读 64,970评论 25 173
  • 上一篇,介绍了grid的浏览器兼容和重要的几个概念,接下来继续介绍grid的容器属性。 Grid(网格) 属性目录...
    codeTao阅读 2,042评论 0 1
  • CSS Grid(网格) 布局(又称为 “Grid(网格)” ),是一个二维的基于网格的布局系统它的目标是完全改变...
    HelloAndyZhang阅读 508评论 0 0
  • 网格线(Grid Line) 构成网格结构的分界线。它们既可以是垂直的(“列网格线(column grid lin...
    晚溪呀阅读 1,164评论 0 0
  • Grid 是CSS中最强大的布局系统。它是2-Dimensional System,这意味着它可以同时处理列和行....
    邢烽朔阅读 2,580评论 0 5