背景
如果要实现下面的布局效果
使用flexbox
- 把1,2合并成左边一个新,再和3 做flex的column布局。
- 1,2在新的盒子4里也做flex 设置row布局
我用flexbox写一下代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
<style>
html,body {
margin: 0;
padding: 0;
}
.container {
width: 400px;
display: flex;
flex-direction: column;
}
.item {
/* border: 1px solid #000; */
height: 50px;
text-align: center;
padding: 10px;
box-sizing: border-box;
}
.flexbox {
width: 100%;
display: flex;
flex-direction: row;
margin-bottom: 10px;
}
.box1 {
background-color: gray;
width: 50%;
margin-right: 10px;
}
.box2 {
background-color: green;
width: 50%;
}
.box3 {
background-color: gold;
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<div class="flexbox">
<div class="item box1">1</div>
<div class="item box2">2</div>
</div>
<div class="item box3">3</div>
</div>
</body>
</html>
缺点:
- 只能实现一维的布局,嵌套的关系开始变得复杂
- 所有的边距都需要单独设置
- 平行的两个元素,由于没有关联性,很难控制一样的自适应宽度
如果只是一次性工作还好,最怕有一天产品跟你说移动端的时候需要做适配。
要响应式变成下面效果
用已有的结构flexbox需要单独调整原有的结构,并且所有已经设置的边距由于物理位置发生变化也需要同步调整
如果 使用flexbox 就要再次嵌套
- 把1,3合并成左边一个新,再和2 做flex的row布局。(注意是1和3,不是1和2)
- 1,2在新的盒子4里也做flex 设置column布局
这还是比较简单的,如果设置的pc是这样
移动端是这样,那该如何是好呢?
这时候grid就有他用武之地。
grid出场
我们以上面最后复杂的网格用grid实现一下,pc的布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试</title>
<style>
html,body {
margin: 0;
padding: 0;
}
.container {
margin: 10px;
display: grid;
grid-template-areas:
'box1 box1 box1'
'box2 box3 box4'
'box5 box6 box6 '
'box7 box7 box7';
padding: 0;
grid-row-gap: 0.24em;
grid-column-gap: 0.24em;
}
.item {
text-align: center;
padding: 10px;
box-sizing: border-box;
}
.box1 {
grid-area: box1;
background-color: gray;
}
.box2 {
grid-area: box2;
background-color: green;
}
.box3 {
grid-area: box3;
background-color: gold;
}
.box4 {
grid-area: box4;
background-color: rgb(0, 200, 255);
}
.box5 {
grid-area: box5;
background-color: rgb(255, 145, 0);
}
.box6 {
grid-area: box6;
background-color: rgb(174, 0, 255);
}
.box7 {
grid-area: box7;
background-color: rgb(163, 33, 122);
}
</style>
</head>
<body>
<div class="container">
<div class="box1 item" >
1
</div>
<div class="box2 item" >
2
</div>
<div class="box3 item" >
3
</div>
<div class="box4 item" >
4
</div>
<div class="box5 item" >
5
</div>
<div class="box6 item" >
6
</div>
<div class="box7 item" >
7
</div>
</div>
</body>
</html>
可以看到代码非常清晰,由于grid天生就是一个二维结构,描述整个网格非常直观。并且可以自己命名网格名,语意化强。
执行效果:
即时是移动的 也只需要调整一下 grid-template-areas的排列参数即可
<style>
@media (max-width: 767px) {
.container {
grid-template-areas:
'box1 box1 box1'
'box2 box3 box4'
'box5 box6 box6 '
'box7 box7 box7';
}
}
</style>
显示效果
注意
实际开发具体的宽度/高度 可以使用rem或 vh/vw 设置不同格子的宽度/高度即可,以及 aspect-ratio: 宽/高,设置更准确的比例宽高。
grid 常用概念
开启grid模式
.container {
display: grid;
}
固定宽高
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
固定比例
.container {
display: grid;
grid-template-columns: 33.33% 33.33% 33.33%;
grid-template-rows: 33.33% 33.33% 33.33%;
}
使用函数固定比例
.container {
display: grid;
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: repeat(3, 33.33%);
}
fr 关键字 等价于flex 的1 的概念,会根据实际设置的两个值做等比计算
.container {
display: grid;
grid-template-columns: 1fr 1fr;
}
grid-row-gap 设置行间隙 grid-column-gap 设置列间隙
.container {
grid-row-gap: 10px;
grid-column-gap: 10px;
}
auto 自动适应宽度
grid-template-columns: 100px auto 100px;
grid-auto-flow
默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行
grid-auto-flow: row;
先列后行
grid-auto-flow: column;
dense 尽量排满,把其他地方满足的往里面填充,顺序无法控制,适合瀑布流效果。
grid-auto-flow: row dense;
水平 ,垂直 对齐,跟flex类似,place-content 水平 ,垂直 的合并
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
place-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
grid-template-areas
是我觉得最有用的属性,当前提前把 grid-area 指定后并填充相关的html,就可以在grid-template-areas 的参数里使用.
如上面例子中,我们只要把grid-area提前设置好
.box1 {
grid-area: box1;
}
.box2 {
grid-area: box2;
}
.box3 {
grid-area: box3;
}
.box4 {
grid-area: box4;
}
.box5 {
grid-area: box5;
}
.box6 {
grid-area: box6;
}
.box7 {
grid-area: box7;
}
html的内容也必须要有7个
<div class="container">
<div class="box1" >
1
</div>
<div class="box2" >
2
</div>
<div class="box3" >
3
</div>
<div class="box4" >
4
</div>
<div class="box5" >
5
</div>
<div class="box6" >
6
</div>
<div class="box7" >
7
</div>
</div>
下面就可以开始排列
.container {
display: grid;
grid-template-areas:
'box1 box1 box1'
'box2 box3 box4'
'box5 box6 box6 '
'box7 box7 box7';
}
注意排列的内容不能多,也不能少,如果你需要更加精致的划分,建议不要用33,可以改成66 ,这样能够更加准确的控制,下面这个设置跟上面是等价的。
.container {
display: grid;
grid-template-areas:
'box1 box1 box1 box1 box1 box1'
'box2 box2 box3 box3 box4 box4'
'box5 box5 box6 box6 box6 box6'
'box7 box7 box7 box7 box7 box7';
}
不需设置的空间 使用.
grid-template-areas: 'a . c'
'd . f'
'g . i';