本文基于阮一峰大神的文章 http://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html
真诚建议大家去原文看,这篇文是我自己根据阮一峰的文章提炼要点,类似于自己的笔记和感悟。
下面开始正题:
grid 中文意思是网格,所以我们可以想象出,它大概是下面这个样子:
每一个方块可以调,每一根线可以调,方块与方块的间距也可以调。
(下面所有的示例,我先给一个完整代码,剩下的就简化了,方便大家查看)
一、方块大小如何调?
方块的大小说到点子上,也就是方块的width
和 height
。调节width
和 height
,基本就三种方式:
- 绝对值,如 100px,10rem,10vh,10vw等。
- 百分比,如 50%
- 绝对值+百分比,如 calc(42% - 0.5rem) 等。(推荐大家去看看
calc
,很好用哦~)
(如果还有其他方式,欢迎大家评论中雅正)
1. 在父元素上操作
1.1 首先,父元素要声明自己是个grid布局的元素(块级或行内级):
- 块级
.container{
display: grid; /* 一个块级的grid布局元素,展示效果为另起一行 */
}
效果图如下:
- 行内级
.container{
display: inline-grid; /* 一个行内的grid布局元素,展示效果为与其他行内元素在一行*/
}
效果图如下:
1.2 声明完grid之后,要操作行和列
-
grid-template-columns
控制每一列的宽度 -
grid-template-rows
控制每一行的高度
这两个属性的属性值可以有多种方式,下面我会一一举例
1.2.1 绝对值
比如 100px 10rem等具体的值。如下代码:
一个三列两行的网格,这个很好理解,大家仔细看代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<style>
.container{
color: #fff;
text-align: center;
display: grid;
grid-template-columns: 100px 200px 100px; /* 三列 */
grid-template-rows: 200px 100px; /* 两行 */
}
.item:nth-child(1){background: #00aa00;}
.item:nth-child(2){background: #0000ff;}
.item:nth-child(3){background: #ff5500;}
.item:nth-child(4){background: #ff00ff;}
.item:nth-child(5){background: #aa0000;}
.item:nth-child(6){background: #55007f;}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
</body>
</html>
效果图如下:
1.2.2 百分比
注意,如果行的控制上也用百分比的话,grid元素要先设置height
height:300px;
grid-template-columns: 20% 50% 30%; /* 三列 */
grid-template-rows: 30% 70%; /* 两行 */
效果图如下:
1.2.3 大招:一些神奇的属性值
1.2.3.1 repeat()
看这个属性设定
grid-template-columns: 100px 100px 100px; /* 三列 */
上面列数小,只有3列,所以可以枚举出来。但如果列数大了呢?比如12列,我们也枚举出来?是不是有点傻?
repeat() 就可以解决这个问题
repeat()接受两个参数,第一个参数是重复的次数(上例是3),第二个参数是所要重复的值
所以可以写成
grid-template-columns: repeat(3,100px); /* 绝对值 */
grid-template-columns: repeat(3,33.33%); /* 百分比 */
grid-template-columns: repeat(3,20px 50px 30px); /* 重复三遍模式,一共9列 */
1.2.3.2 auto-fill
有时候,里面的小格子大小固定,但外面的大容器大小不固定,想要小格子尽可能填充满大容器的每一行或每一列,这时可以用到auto-fill
先看充满一行:
grid-template-columns: repeat(auto-fill, 130px); /* 尽可能充满一行 */
效果图:
充满一列
height: 500px;
grid-auto-flow: column; /* 先确定按列排 */
grid-template-rows: repeat(auto-fill, 120px);
效果图:
1.2.3.3 fr
网格布局提供了fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。
个人认为单纯使用fr来表示比例没有任何意义,和百分比效果一样,顶多是写法上更方便一些,因为不用计算百分比。fr和绝对值配合使用,才会发挥出巨大的作用
比如说,现在有这么个需求:一个div,宽度随屏幕自适应,里面有三个元素排成一行,第一个元素100px的宽度,第三个元素宽度是第二个的二倍,要求三个元素充满整个div。我们就可以使用fr来实现。
grid-template-columns: 100px 1fr 2fr;
效果图如下:
1.2.3.4 minmax()
设置最小最大的范围。
grid-template-columns: 100px 100px minmax(120px ,1fr);
1.2.3.5 auto
经常适用于以下场景:
一个div,宽度随屏幕自适应,里面三个元素排成一行,第一个和第三个各100px,第二个充满剩余空间
grid-template-columns: 100px auto 100px;
效果图如下:
二、网格线
1. 指定网格线名称
grid-template-columns属性和grid-template-rows属性里面,还可以使用方括号,指定每一根网格线的名字,方便以后的引用
grid-template-columns: [cl1] 100px [cl2] auto [cl3] 100px [cl4];
grid-template-rows: [rl1] 100px [2l2] auto [rl3];
三、方块与方块的间距
- 设置列间距
column-gap
- 设置行间距
row-gap
- gap: <row-gap> <column-gap>; 前两者简写形式
grid-template-columns: [cl1] 100px [cl2] auto [cl3] 100px [cl4];
grid-template-rows: [rl1] 100px [2l2] auto [rl3];
column-gap: 10px;
row-gap: 20px;
效果图:
四、布局相关
1. grid-template-areas
grid布局会分出很多小单元格,这个属性就可以给单元格命名,方便引用
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 . c'
'd e .'
'g . i';
2. grid-auto-flow
默认排列单元格的方式
- 按行排: grid-auto-flow: row;
- 按列排: grid-auto-flow: column;
像不像flex布局里的 flex-direction
grid-auto-flow: column;
grid-template-columns: 50px auto 50px ;
grid-template-rows: 50px auto ;
效果图如下(仔细体会行和列哦,并没有改变,只是排列方式变了):
** 有一个 dense ** 的东西,指定某个单元格放在确定位置,其他的如何摆放,说实话我觉得用处不大,先不写了。
3. justify-items、align-items 、place-items
- justify-items:单元格内容的水平位置
主要有四个值:stretch | start | end | center。
stretch是默认值,拉伸,占满整个单元格位置。
给大家看一个start的完整代码。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style type="text/css">
#container{
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-items: start; /* start 布局 */
}
.item {
font-size: 2em;
text-align: center;
border: 1px solid #000;
}
.item-1 {background-color: #ef342a;}
.item-2 {background-color: #f68f26;}
.item-3 {background-color: #4ba946;}
.item-4 {background-color: #0376c2;}
.item-5 {background-color: #c077af;}
.item-6 {background-color: #f8d29d;}
.item-7 {background-color: #b5a87f;}
.item-8 {background-color: #d0e4a9;}
.item-9 {background-color: #4dc7ec;}
</style>
</head>
<body>
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
<div class="item item-9">9</div>
</div>
</body>
</html>
效果图:
- align-items:单元格内容的垂直位置,与上面的justify-items 同理。
- place-items:前面两者的合称
4. justify-content、align-content、place-content
- justify-content: 内容区域(那些聚在一起的单元格)在整个容器内水平方向的布局
取值:start | end | center | stretch | space-around | space-between | space-evenly;
start是默认值。
举一个center的例子,下面是完整代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style type="text/css">
#container{
display: grid;
width: 500px;
height: 500px;
border: 1px solid #000000;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-content: center;
}
.item-1 {background-color: #ef342a;}
.item-2 {background-color: #f68f26;}
.item-3 {background-color: #4ba946;}
.item-4 {background-color: #0376c2;}
.item-5 {background-color: #c077af;}
.item-6 {background-color: #f8d29d;}
.item-7 {background-color: #b5a87f;}
.item-8 {background-color: #d0e4a9;}
.item-9 {background-color: #4dc7ec;}
</style>
</head>
<body>
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
<div class="item item-9">9</div>
</div>
</body>
</html>
效果图:
- align-content : 内容区域(那些聚在一起的单元格)在整个容器内水平方向的布局
- place-content属性是align-content属性和justify-content属性的合并简写形式。
5. grid-auto-columns、grid-auto-rows
比如网格只有3列,但是某一个项目指定在第5行。这时,浏览器会自动生成多余的网格,以便放置项目。
一个代码示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style type="text/css">
#container{
display: grid;
width: 500px;
height: 500px;
border: 1px solid #000000;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
.item-1 {background-color: #ef342a;}
.item-2 {background-color: #f68f26;}
.item-3 {background-color: #4ba946;}
.item-4 {background-color: #0376c2;}
.item-5 {background-color: #c077af;}
.item-6 {background-color: #f8d29d;}
.item-7 {background-color: #b5a87f;}
.item-8 {background-color: #d0e4a9;}
.item-9 {background-color: #4dc7ec;}
.item-1{
grid-row-start: 4;
grid-row-start: 5;
}
</style>
</head>
<body>
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
<div class="item item-9">9</div>
</div>
</body>
</html>
效果图:
6. grid-column-start、grid-column-end、grid-row-start、grid-row-end
指定某一项目的四个边框,从而指定某一项目的具体位置,如下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style type="text/css">
#container{
display: grid;
grid-template-columns: 100px 100px 100px ;
grid-template-rows: 100px 100px 100px ;
}
.item-1 {background-color: #ef342a;}
.item-2 {background-color: #f68f26;}
.item-3 {background-color: #4ba946;}
.item-4 {background-color: #0376c2;}
.item-5 {background-color: #c077af;}
.item-6 {background-color: #f8d29d;}
.item-7 {background-color: #b5a87f;}
.item-8 {background-color: #d0e4a9;}
.item-9 {background-color: #4dc7ec;}
.item-1{
/* 指定位置 */
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 2;
grid-column-end: 3;
}
</style>
</head>
<body>
<div id="container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
<div class="item item-4">4</div>
<div class="item item-5">5</div>
<div class="item item-6">6</div>
<div class="item item-7">7</div>
<div class="item item-8">8</div>
<div class="item item-9">9</div>
</div>
</body>
</html>
效果图:
7. grid-area
指定项目放在哪一个区域,主要有两种方法
7.1 直接指定区域
#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';
}
.item-1{
grid-area: f; /* 直接指定 */
}
7.2 通过线来指定区域
#container{
display: grid;
grid-template-columns: 100px 100px 100px ;
grid-template-rows: 100px 100px 100px ;
}
.item-1{
grid-area: 2/3/3/4;
}
8. justify-self、align-self、place-self
设置单元格内容的水平或垂直位置,只作用于单个项目
太简单了。。。跟上面justify-items一样的原理。
到这儿就算完了,太不容易了,好懵。。。