grid布局
grid布局就是网格布局,虽然我们平常用得少,基本都是用flex布局,但是其实有些地方使用grid布局还是挺不错的,而且grid在处理多行行列二维布局的时候尤为方便,尤其是移动端、或者整体布局。
转为grid
我们知道我们css盒子一般分为块级、行内块、行内元素三种,而我们想转换他们的时候,就要使用display,或者我们使用flex布局的时候,也要使用display将其转为弹性盒子。而grid网格布局也是这样的。将其他盒子转为网格布局使用display有两个选项,一个是grid,一个是inline-grid。
display:grid;是将盒子转为块级的网格布局;display:inline-grid;是将盒子转为行内块的网格布局。
行与列
既然grid主要是处理二维的,那么二维是有许多行与列组成的,那么grid的行与列咋定义呢?
- grid-template-columns:定义列
- grid-template-rows:定义行
他们的样式属性都是一样的。他们可以使用具体的像素值px,也可以使用百分比,还可以使用fr和auto。
假如我们定义一个3行3列的九宫格:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 200px 200px 200px;
grid-template-rows: 200px 200px 200px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
我们发现现在这个div盒子已经是3*3的九宫格布局了,其中每一个格子就是200px * 200px;
我们还可以使用百分比布局,百分比布局就是按照本身盒子宽高为基准的。Emm,这个没啥好说的。
fr这个单位的意思和flex布局中的flex-grow的放大因子类似(计算方法类似)。都是将剩余空间进行再分配。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 200px 200px 200px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: 200px 200px 200px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 100px 2fr 1fr;
grid-template-rows: 200px 200px 200px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
我们发现上面情况,得到的结果都不一样。
第一种情况是没有指定列的宽度,全部使用的是
1fr,那么该盒子本身的宽度是600px,那么就将600px平分为3份,每一份的值就是600/3 = 200px。
第二种情况是将盒子分为3列,但是是将盒子分为了4份,那么每一份就是600/4 = 150px。而第一列和第三列占一份,那么他们的宽度就是150px,而第二列占了两份,那么它的宽度就是300px。
第三种情况是将盒子分为3列,但是第一列的宽度100px已经已知了,那么就将剩下的500px平分为3份,每一份就是500/3,而第二列占两份,第三列占1份。
此外:还可以使用auto;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 100px auto;
grid-template-rows: 200px 200px 200px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
auto的意思就是将剩余空间占满的意思,其实一般使用auto还是用得少,这种情况下用1fr就可以了。
repeat函数
此外我们还可以在grid-template-columns和grid-template-row中使用repeat函数。
repeat函数的意思就是重复的意思,它有两个参数:
- 第一个参数:重复的次数
- 第二个参数:如果是一个值,就是每次的宽度(高度)。如果是多个值,就是重复的几行或几列。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: repeat(2,50px 200px);
grid-template-rows: repeat(3,1fr);
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
我们发现我们这里就是一个3行4列的网格。
因为grid-template-rows: repeat(3,1fr);表示一个3行,每一行为1fr。
而grid-template-columns: repeat(2,50px 200px);中的repeat(2,50px 200px);表示重复2次,每一次就是宽为50px和宽为200px的2列。
所以最后就成了3行4列。
gap
- grid-column-gap:列与列之间的距离
- grid-row-gap:行与行之间的距离
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(3,1fr);
grid-row-gap:50px;
grid-column-gap:50px;
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
每行之间有50px的距离,每列之间有50px之间的距离。
grid-template-areas
通过引用grid-area属性指定的网格区域的名称来定义网络模板,重复网格区域的名称会使内容扩展到这些单元格.(其实就是给每一个单元格一个名字)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 1fr 1fr 1fr ;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: "a b c"
"d d d"
"e f f";
}
</style>
</head>
<body>
<div id="box">
</div>
</body>
</html>
grid-line线
其实我们在定义了行与列之后,网格盒子会自动给我们的每一行与每一列自动添加一条线。
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(3,1fr);
}
也就是说,第一行就是在1和2之间,第二行就是3和4之间,以此类推...
此外,我们也可以自己给每一条线重新命名。重新命名是在定义行与列的时候定义的。
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: [line1] 200px [line2] 200px [line3] 200px [line4];
grid-template-rows: [first] 200px [second] 200px [third] 200px [last];
}
(不过我还是喜欢使用默认的数字哈哈~)
网格的使用
现在我们是创建好了网格,但是我们要怎么使用这个网格呢?我们怎样把我们需要的元素填充到里面呢?
默认填充
一般情况下,我们写的元素会默认的一行一行的进行填充的,且默认填充一个网格。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin:0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 200px 200px 200px ;
grid-template-rows: 200px 200px 200px ;
}
.item {
background-color: red;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
box-sizing: border-box;
padding: 20px;
background-clip: content-box;
}
</style>
</head>
<body>
<div id="box">
<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 class="item">7</div>
</div>
</body>
</html>
使用grid-line填充
我们也可以指定某个元素在网格中的位置,以及它占用的网格数量。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 200px 200px 200px ;
grid-template-rows: 200px 200px 200px ;
}
.item {
background-color: red;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
box-sizing: border-box;
padding: 20px;
background-clip: content-box;
}
.item:nth-child(1) {
grid-row-start: 1;
grid-row-end: 4;
grid-column-start: 1;
grid-column-end: 2;
}
.item:nth-child(2) {
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 2;
grid-column-end: 4;
}
.item:nth-child(3) {
grid-row: 2 / 4;
grid-column: 2 /4 ;
}
</style>
</head>
<body>
<div id="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
</body>
</html>
我们发现,我们可以使用grid-row-start和grid-row-end来指定我们这个元素的位置和大小。
.item:nth-child(1) {
grid-row-start: 1;
grid-row-end: 4;
grid-column-start: 1;
grid-column-end: 2;
}
它的意思是它从行的第一条线开始填充,到第四条线填充结束;然后再从列的第一条线开始填充,到列的第二条线结束填充。
grid-row和grid-column是简写形式。
grid-row:grid-row-start / grid-row-end;
grid-column: grid-column-start / grid-column-end;
当然,他也可以配合我们自定义的线一起使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: [line1] 200px [line2] 200px [line3] 200px [line4];
grid-template-rows: [first] 200px [second] 200px [third] 200px [last];
}
.item {
background-color: red;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
box-sizing: border-box;
padding: 20px;
background-clip: content-box;
}
.item:nth-child(1) {
grid-row:second/third;
grid-column: line2/line3;
}
</style>
</head>
<body>
<div id="box">
<div class="item">1</div>
</div>
</body>
</html>
使用grid-area填充
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 1fr 1fr 1fr ;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: "a b c"
"d d d"
"e f f";
}
.item {
background-color: red;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
box-sizing: border-box;
padding: 20px;
background-clip: content-box;
}
.item:nth-child(1) {
grid-area: d;
}
</style>
</head>
<body>
<div id="box">
<div class="item">1</div>
</div>
</body>
</html>
呜呼,是不是很快啊~哈哈
justify-content与align-content
justyfy管主轴,align管副轴。(我是这样记的,和flex一样的)
如果我们定义的网格没有布满整个盒子:
#box {
width: 600px;
height: 600px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: 100px 100px 100px ;
grid-template-rows: 100px 100px 100px;
}
这时我们想移动整个网格,就要使用justfy-content与align-content了。他的属性值有6个:我们都应该很熟悉,全是flex里面的...
- start:网格与网格容器的左边/顶部对齐(默认)
- end:网格与网格容器的右边/底部对齐
#box {
justify-content: end;
align-content: end;
}
- center:网格与网格容器的中间对齐
#box {
justify-content: center;
align-content: center;
}
- space-around:在 grid item 之间设置均等宽度/高度的空白间隙,其外边缘间隙大小为中间空白间隙宽度的一半
#box {
justify-content: space-around;
align-content: space-around;
}
- space-between:在 grid item 之间设置均等宽度/高度空白间隙,其外边缘无间隙
#box {
justify-content: space-between;
align-content: space-between;
}
- space-evenly:每个 grid item 之间设置均等宽度/高度的空白间隙,包括外边缘
#box {
justify-content: space-evenly;
align-content: space-evenly;
}
place-content属性 设置 align-content 和 justify-content 的简写
#box {
place-content: <align-content> <justify-content>;
}
如果省略第二个值,则将第一个值同时分配给这两个属性
justfy-items与align-items
就是操作我们网格里面的所有的小盒子的。(content是操作整个网格,item是操作网格里的子盒子)他的属性有4个:
- start:内容与网格区域的左端/顶端对齐(默认)
#box {
width: 300px;
height: 300px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
.item {
width: 50px;
height: 50px;
background-color: red;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
box-sizing: border-box;
padding: 2px;
background-clip: content-box;
}
- end:内容内容与网格区域的右端/底部对齐
#box {
width: 300px;
height: 300px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: repeat(3,1fr) ;
grid-template-rows: repeat(3,1fr);
justify-items:end;
align-items:end;
}
- center:内容位于网格区域的中间/垂直中心位置
#box {
width: 300px;
height: 300px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: repeat(3,1fr) ;
grid-template-rows: repeat(3,1fr);
justify-items:center;
align-items:center;
}
- stretch:内容宽度/高度占据整个网格区域空间(当子盒子没有设置具体的宽高才起作用,且为默认)
#box {
width: 300px;
height: 300px;
margin: 10px auto;
border: 1px solid red;
display: grid;
grid-template-columns: repeat(3,1fr) ;
grid-template-rows: repeat(3,1fr);
}
.item {
background-color: red;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
box-sizing: border-box;
padding: 2px;
background-clip: content-box;
}
place-items属性 设置 align-items和 justify-items的简写
#box {
place-items: <align-items> <justify-items>;
}
如果省略第二个值,则将第一个值同时分配给这两个属性
justify-self与align-self
沿着行/列轴对齐grid item 里的内容。此属性对单个网格项内的内容生效的。作用和justify-items与align-items一模一样。就是对象不一样了,justify-items与align-items是在网格容器盒子上面设置的,且对它的所有子盒子都有效;而justify-self与align-self是在网格容器里的子盒子上面设置的,且只对自己有效。
它的属性值和justify-items与align-items也是一样的,start、end、center、stretch。
它也有简写:
place-self属性
设置 align-self 和justify-self 的简写形式
#box {
place-content: <align-self> <justify-self> | auto;
}
如果省略第二个值,则将第一个值同时分配给这两个属性
其实如果会flex布局的话,掌握这个grid布局真的很轻松唉!