作者:李嘉豪 lijiahao043@ke.com
本文想用一个页面布局为例,横向对比一下 float,flex 和 grid 的优劣。
假如 UI 给了你一个原型图,让你实现如下布局。
float 方案
实现思路
首先,我们用最老的 float 方案试一试。我们的思路如下:
- 首先 2 和 3 往左浮动,并给它们加一个 bfc 的 container;
- 接着,给,2,3,1 加一个 container 并为之添加浮动,这个 container 与 4 的浮动同级。
- 最后,需要给 2,3,1,4 加一个大的 bfc。5 正常排列即可。
代码
那么我们用代码实现一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
font-size: 12px;
}
.container1 {
overflow: hidden;
}
.container2 {
float: left;
}
.box {
width: 100px;
height: 100px;
margin: 5px;
background-color: orange;
float: left;
font-size: 4em;
text-align: center;
line-height: 100px;
}
.box1 {
width: 210px;
height: 210px;
float: none;
line-height: 210px;
}
.box5 {
float: none;
width: 320px;
height: 100px;
}
.box4 {
width: 100px;
height: 320px;
line-height: 320px;
}
.bfc {
overflow: hidden;
}
</style>
</head>
<body>
<!-- 用 float 可以实现与 grid 相同的效果,但实现难度大且不如 grid 清晰,同时需要了解 bfc 相关的知识 -->
<div class="container">
<div class="bfc">
<div class="container2">
<!-- 需要用 bfc 清除浮动 -->
<div class="bfc">
<div class="box box2">2</div>
<div class="box box3">3</div>
</div>
<div class="box box1">1</div>
</div>
<div class="box box4">4</div>
</div>
<div class="box box5">5</div>
</div>
</body>
</html>
可以看到,使用 float 有一个比较大的弊端,就是为了清除浮动,你需要频繁的增加 bfc container,所以 html 代码写下来,到处都是 div 容器,不是很清晰。并且,使用 float 需要要求使用者对 bfc 的知识理解的比较清晰。
flex 方案
flex 的实现和 float 非常相似,区别是,由于 flex 的直接子元素自带 bfc,所以你不需要额外的添加 bfc 容器解决外边距重叠问题,也不需要清除浮动。
实现思路
- 2 和 3 装到一个 flex container 里面
- 2 和 3 的 container 和 1 放到一个 container 里,记为 c1
- c1 和 4 放到一个 flex container 里面
- 5 正常排
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container{
font-size: 12px;
}
.box {
background-color: orange;
margin: 5px;
font-size: 4em;
text-align: center;
line-height: 100px;
}
.flex {
display: flex;
}
.box2,
.box3 {
width: 100px;
height: 100px;
}
.box1 {
width: 210px;
height: 210px;
line-height: 210px;
}
.box4 {
width: 100px;
height: 320px;
line-height: 320px;
}
.box5 {
width: 320px;
height: 100px;
}
</style>
</head>
<body>
<div class="container">
<!-- flex 的直接下级元素会创建 bfc -->
<div class="flex">
<div>
<div class="flex">
<div class="box box2">2</div>
<div class="box box3">3</div>
</div>
<div class="box box1">1</div>
</div>
<div class="box box4">4</div>
</div>
<div class="box box5">5</div>
</div>
</body>
</html>
grid 方案
用 grid 方式实现的代码要比前两者整齐的多
实现思路
- 5 个盒子直接顺序放到一个容器里
- 容器使用 grid,分别用 grid-template-rows 和 grid-template-columns 指定行和列,用 grid-gap 指定元素间缝隙。
- 子元素分别用 grid-row 和 grid-column 指定行和列从哪条网格线到哪条网格线
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
/* 使用 grid 布局 */
display: grid;
/* 3 列 4 行 */
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(4, 100px);
/* 内部元素的缝隙 */
grid-gap: 10px;
font-size: 12px;
}
.box {
background-color: orange;
font-size: 4em;
text-align: center;
line-height: 100px;
}
.box1 {
grid-row: 2/4;
/*表示从第二个网格开始,从第四个网格结束*/
grid-column: 1/3;
line-height: 200px; /* text-align 使得文字水平居中,line-height 与 height 一致让文字垂直居中 */
}
.box4 {
grid-row: 1/4;
grid-column: 3/4;
line-height: 300px;
}
.box5 {
grid-row: 4/5;
grid-column: 1/4;
}
</style>
</head>
<body>
<div class="container">
<div class="box1 box">1</div>
<div class="box2 box">2</div>
<div class="box3 box">3</div>
<div class="box4 box">4</div>
<div class="box5 box">5</div>
</div>
</body>
</html>
三者比较来看,似乎 grid 完胜,但其实 grid 也有自身的问题,那就是它的兼容性做的并不好,尤其是 h5。我们引用 segment fault 论坛中一位老哥的评价
但如果您能确定的是,使用你页面的人全部为 pc web 用户并且他们使用的浏览器版本比较新,你可以方向大胆的用 grid。grid 就是为了干这个事的。(解决复杂布局)
参考资料
【1】mdn developer.mozilla.org/zh-CN/docs/…
【2】阮一峰 www.ruanyifeng.com/blog/2019/0…
【3】segment fault segmentfault.com/q/101000000…
【4】我的代码 github.com/Ethan199412…