Gird布局详解
一、什么是 Grid 布局?
CSS Grid Layout(网格布局)是 CSS 提供的二维布局系统,可以同时在行(row)和列(column)两个方向上对元素进行排列。
它和 Flexbox 不同,Flexbox 是一维布局(只能按行或列排),而 Grid 是二维布局,可以轻松实现复杂的跨行、跨列布局。
特点:
- 二维布局:同时控制行和列,对应一维布局复杂度也随之增加
- 跨行跨列:元素可以跨多个单元格,一维度布局需要层层嵌套来做这些效果
-
语义清晰:
grid-template-areas像地图一样描述布局,布局就像ASCLL表一样清晰直观 -
响应式友好:只改 Grid 定义,不动 HTML,就能重排布局,经常配合
@media使用 - 现代浏览器支持好:桌面端和移动端几乎全覆盖(IE11 部分支持旧语法),现代浏览器基本都是支持的,排除一下老旧项目(政府、银行等)还在使用
二、基本概念
容器和项目
什么是容器?
设置了 display: grid 或 display: inline-grid 的元素,就是 Grid 容器,容器的直接子元素就是 Grid 项目。容器负责定义整个网格的结构(行、列、间距、对齐方式等)。
什么是项目?
Grid 容器的直接子元素就是 Grid 项目,项目可以通过属性控制它在网格中的位置、跨行跨列、对齐方式等。
行和列
容器里面的水平区域称为"行"(row),垂直区域称为"列"(column)。
下图水平深色区域就是“行”,垂直深色区域就是“列”
![]()
单元格
行和列的交叉区域,称为"单元格"(cell),n行和m列会产生n x m个单元格。比如,3行3列会产生9个单元格。
网格线
划分网格的线,称为"网格线"(grid line)。水平网格线划分出行,垂直网格线划分出列,n行有n + 1根水平网格线,m列有m + 1根垂直网格线,比如三行就有四根水平网格线。
如下图就有5根水平网格线和5根垂直网格线
![]()
三、容器属性
display:grid | inline-grid
作用:指定一个容器采用网格布局
语法:
.container{
display: grid | inline-grid;
}
注意:设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效。
grid-template-columns与grid-template-rows
作用:grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高
实例:指定了一个三行三列的网格,列宽和行高都是100px
![]()
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
.container > div {
width: 60px;
height: 60px;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
repeat()
作用:使用repeat()函数,简化重复的值,接受两个参数,第一个参数是重复的次数,第二个参数是所要重复的值,也可以重复某个模式
实例:
- 简单重复值
![]()
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
- 重复某个模式
![]()
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
auto-fill与auto-fit
作用:单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充,只有当容器足够宽,可以在一行容纳所有单元格,并且单元格宽度不固定的时候,才会有差异:auto-fill会用空格子填满剩余宽度,auto-fit则会尽量扩大单元格的宽度
实例:
例子中宽设置了400px,高设置200px,属性auto-fill,高400px/100px=4个格子,宽200px/100px=2个格子,所以超出的第九个被空放了
![]()
.container {
width: 400px;
height: 200px;
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
grid-template-rows: repeat(auto-fill, 100px);
}
fr
作用:为了方便表示比例关系,网格布局提供了fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍
实例:
![]()
.container {
width: 400px;
display: grid;
grid-template-columns: 300px 1fr 2fr;
grid-template-rows: repeat(3, 100px);
}
minmax
作用:minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值
实例:
每行第三列位置宽度100px~2fr
![]()
.container {
display: grid;
grid-template-columns: 1fr 1fr minmax(100px, 2fr);
grid-template-rows: repeat(3, 100px);
}
auto
作用:由浏览器自己决定长度
实例:
![]()
.container {
width: 400px;
display: grid;
grid-template-columns: 100px auto 100px;
grid-template-rows: repeat(3, 100px);
}
自定义网格线名称
作用:指定每一根网格线的名字,方便以后的引用
实例:
指定网格布局为3*3,因此有4根垂直网格线和4根水平网格线,每个网格线可以指定多个名字,比如[r4 xipiker666]
.container {
display: grid;
grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4 xipiker666];
}
grid-columns-gap(columns-gap)与grid-rows-gap(rows-gap)与grid-gap(gap)
作用:grid-columns-gap设置列间距、grid-rows-gap设置行间距,可以分别简写为columns-gap和rows-gap,grid-gap设置行列间距grid-gap: <行间距> <列间距> ,grid-gap可以简写为gap,如果行和列的值相等可以gap: xxpx
实例:
![]()
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
gap: 20px;
}
grid-template-areas
作用:网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成
实例:
- 划分出9个单元格
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-template-areas:
'a b c'
'd e f'
'g h i';
gap: 20px;
}
- 多个单元格合并成一个区域
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-template-areas:
'a a a'
'b b b'
'c c c';
gap: 20px;
}
- 某些区域不需要利用,则使用
.表示
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-template-areas:
'a . a'
'b . b'
'c . c';
gap: 20px;
}
grid-auto-flow
作用:容器的子元素的排序方式,属性值row先行后列,属性值columns先列后行,属性值row dense子项目指定位置后再先行后列排序,属性值columns dense子项目指定位置后再先列后行排序
实例:
-
row先行后列
![]()
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-auto-flow: row;
}
-
columns先列后行
![]()
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-auto-flow: column;
}
-
row dense子项目指定位置后先行后列
![]()
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-auto-flow: row dense;
}
.item_first {
grid-column-start: 1;
grid-column-end: 3;
}
.item_two {
grid-column-start: 1;
grid-column-end: 3;
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
-
columns dense子项目指定位置后先列后行
![]()
.container {
width: 400px;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-auto-flow: column dense;
}
.item_first {
grid-column-start: 1;
grid-column-end: 3;
}
.item_two {
grid-column-start: 1;
grid-column-end: 3;
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
justify-items与align-items与place-items
作用:justify-items属性设置单元格内容的水平位置,align-items属性设置单元格内的垂直位置,place-items属性是justify-items和align-items的组合属性
实例:
justify-items: start | center | end | stretch
![]()
.container {
width: 300px;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
justify-items: center;
}
.container > div {
width: 60px;
height: 60px;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
align-items: start | center | end | stretch
![]()
.container {
width: 300px;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
align-items: center;
}
.container > div {
width: 60px;
height: 60px;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
place-items: <align-items> <justify-items>
![]()
.container {
width: 300px;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
place-items: center end;
}
.container > div {
width: 60px;
height: 60px;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
justify-content与align-content与place-content
作用:justify-content属性设置内容区域在容器里面的水平位置,align-content属性设置内容区域在容器里面的垂直位置,place-content属性是justify-content和align-content的组合属性
实例:
justify-content: start | end | center | stretch | space-around | space-between | space-evenly
![]()
.container {
width: 600px;
background: #f9f9f9;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
justify-content: center;
}
.container > div {
width: 60px;
height: 60px;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
align-content: start | end | center | stretch | space-around | space-between | space-evenly
![]()
.container {
width: 600px;
height: 400px;
background: #f9f9f9;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
align-content: center;
}
.container > div {
width: 60px;
height: 60px;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
place-content: <align-content> <justify-content>
![]()
.container {
width: 600px;
height: 400px;
background: #f9f9f9;
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
place-content: center center;
}
grid-auto-columns与grid-auto-rows
作用:可以理解为,现有网格的外部设置多余的网格,用来放超出的子项目
实例:
grid-auto-columns
![]()
.container {
background: #f9f9f9;
display: grid;
grid-template-columns: 100px 100px;
grid-template-rows: 50px;
grid-auto-rows: 80px
grid-auto-flow: row; /*这里要设置按照行方向填充,可以不设置,因为默认按照行方向*/
}
grid-auto-rows
![]()
.container{
background: #f9f9f9;
display: grid;
grid-template-rows: 50px 50px;
grid-template-columns: 100px;
grid-auto-columns: 150px;
grid-auto-flow: column; /*注意这里要设置按照列方向填充,必须设置,因为默认按照行防线*/
}
grid-template与grid
作用:grid-template属性是grid-template-columns、grid-template-rows和grid-template-areas这三个属性的合并简写形式,grid属性是grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow这六个属性的合并简写形式
四、项目属性
grid-column-start、grid-column-end与grid-row-start、grid-row-end
作用:可以理解为设置项目占多少个网格线,分别定位在哪根网格线
实例:
-
grid-column-start: <number>左边框所在的垂直网格线、grid-column-end: <number>右边框所在的垂直网格线
![]()
.container {
background: #f9f9f9;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
}
.item_first {
grid-column-start: 1;
grid-column-end: 3;
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
<div class="container">
<div className="item_first">1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
-
grid-row-start: <number>上边框所在的垂直网格线、grid-row-end: <number>下边框所在的垂直网格线
![]()
.container {
background: #f9f9f9;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
}
.item_first {
grid-row-start: 1;
grid-row-end: 3;
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
<div class="container">
<div className="item_first">1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
</div>
grid-column与grid-row
作用:grid-column属性是grid-column-start和grid-column-end的简写形式、grid-row属性是grid-row-start和grid-row-end的简写形式
实例:
grid-column: <grid-column-start> / <grid-column-end>grid-row: <grid-row-start> / <grid-row-end>
grid-area
作用:指定项目放在哪个区域,grid-area属性还可用作grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并简写形式,直接指定项目的位置
实例:
- 指定放在哪个区域
![]()
.container {
background: #f9f9f9;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
grid-template-areas:
'a b c'
'd e f'
'g h i';
}
.item_first {
grid-area: e;
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
grid-area: <row-start> / <column-start> / <row-end> / <column-end>
![]()
@pos: ~'1 / 1 / 3 / 3';
.container {
background: #f9f9f9;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
}
.item_first {
grid-area: @pos;
}
.container > div {
width: 100%;
height: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
justify-self与align-self与place-self
作用:justify-self属性设置单元格内容的水平位置、align-self属性设置单元格内容的垂直位置,place-self属性是justify-self和align-self的属性组合
实例:
![]()
.container {
background: #f9f9f9;
display: grid;
grid-template-rows: repeat(3, 100px);
grid-template-columns: repeat(3, 100px);
}
.item_first {
justify-self: center;
align-self: center;
}
.container > div {
width: 60px;
height: 60px;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
五、常见布局案例
三列等宽布局
效果
![]()
代码
.container {
background: #f9f9f9;
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.container > div {
width: 100%;
border: 1px solid #ccc;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
font-weight: bold;
}
<div className="container">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
圣杯布局
效果
![]()
代码
.container {
display: grid;
grid-template-areas:
'header header'
'sidebar main'
'footer footer';
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 40px;
gap: 10px;
}
.header {
grid-area: header;
background: lightblue;
}
.sidebar {
grid-area: sidebar;
background: lightgoldenrodyellow;
}
.main {
grid-area: main;
background: lightgreen;
}
.footer {
grid-area: footer;
background: lightpink;
}
<div class="container">
<div className="header">header</div>
<div className="sidebar">sidebar</div>
<div className="main">main</div>
<div className="footer">footer</div>
</div>
媒体查询响应式布局(Gird+Flex最佳拍档)
效果
屏幕宽度小于等于660px
![]()
屏幕宽度小于等于1024
![]()
屏幕宽度大于1024
代码
<div class="dashboard">
<div class="stats">Stats</div>
<div class="overview">Overview</div>
<div class="lifecycle">Lifecycle</div>
<div class="calendar">Calendar</div>
<div class="monitor">Monitor</div>
<div class="ladder">Ladder</div>
<div class="stage">Stage</div>
</div>
.dashboard {
display: grid;
gap: 20px;
padding: 20px;
/* 桌面端布局 */
grid-template-columns: 2fr 2fr 1fr;
grid-template-areas:
'stats stats stats'
'overview lifecycle calendar'
'monitor ladder calendar'
'stage stage stage';
}
.dashboard > div {
background: #eee;
padding: 10px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
font-weight: bold;
}
.stats {
grid-area: stats;
}
.overview {
grid-area: overview;
}
.lifecycle {
grid-area: lifecycle;
}
.calendar {
grid-area: calendar;
}
.monitor {
grid-area: monitor;
}
.ladder {
grid-area: ladder;
}
.stage {
grid-area: stage;
}
@media (max-width: 1024px) {
.dashboard {
grid-template-columns: 1fr 1fr;
grid-template-areas:
'stats stats'
'overview lifecycle'
'calendar calendar'
'monitor ladder'
'stage stage';
}
}
@media (max-width: 600px) {
.dashboard {
grid-template-columns: 1fr;
grid-template-areas:
'stats'
'overview'
'lifecycle'
'calendar'
'monitor'
'ladder'
'stage';
}
}
Grid瀑布流布局
效果
![]()
代码
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 10px;
grid-auto-flow: dense;
gap: 10px;
}
.item {
background: lightblue;
}
.item1 {
grid-row-end: span 15;
}
.item2 {
grid-row-end: span 25;
}
.item3 {
grid-row-end: span 20;
}
<div class="container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item1">4</div>
</div>
六、总结
上述内容主要参考,大家可以参考原文,如果能帮到您,欢迎点赞、收藏、+关注