gird布局和flex布局对比

189 阅读5分钟

经典flex布局示例

导航

场景

image-20230731105421260.png

场景特点: 一维布局、内容决定box大小

布局分析

image-20230731111030273.png

核心实现

.container {
  display: flex;
  gap: 8px;
}
.right {
  margin-left: auto;
}

完整代码见附录1

绝对底部

场景

image-20230731113128881.png

场景特点:一维布局(纵向)、绝对底部

布局分析

image-20230731114341648.png

由图可见,使用绝对底部时,无论title、jpg、description部分如何调整都不会影响整体布局。

核心实现

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.container > div {
  flex: 1 1 auto;
}

完整代码见附录2

经典grid场景示例

11-responsive-areas.png

由上图可知,grid在复杂组件布局(比如页面框架)上具有优势。

grid二维优势对比示例

场景

image-20230731122039790.png

场景特点: 二维布局,垂直对齐、水平靠左对齐;box大小等比,需要考虑1920px和1280px场景

布局分析

image-20230731122735147.png

核心实现

gird布局实现

display: grid;
gap: 8px;
// fr单位表示可用空间的一份,所有box按比例分配可用空间
grid-template-columns: repeat(3, 1fr);

完整代码见附录3

flex布局实现

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.container > * {
  // 允许在150px的基准上伸缩,150px表明一行只允许放置3个box
  flex: 1 1 150px;
}
// 设置一个相同大小的伪元素作为最后一个box
.container::after {
  content: '';
  flex: 1 1 150px;
}

完整代码见附录4

对比

grid在实现二维布局上更灵活,flex在实现如上布局时略显吃力。如果一列box数从3改为4,grid只需将repeat中3改为4,而flex需要较大调整。

注意:当允许弹性box换行时,每个新行都变成了一个新的弹性容器。空间分布1只在行内进行。

思考

问题:grid布局是flex布局的扩展还是替代?

问题详情: 除了少数内容决定盒子大小的场景,grid在布局决定盒子大小的场景是不是可以覆盖到并替代flex?

os:我们知道一维布局下,我们一般推荐使用flex,但布局决定盒子大小的一维布局场景下,使用flex比grid更具优势吗?

场景&布局

image-20230731152036083.png

场景特点: 一维布局、box等比展示

核心实现对比

/* 方式一:flex布局 */
.container {
  display: flex;
  gap: 8px;
}
.container > * {
  flex-grow: 1
}

/* 方式二:grid布局 */
.container {
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(3, 1fr);
}

完整代码见附录5

对比可知,flex布局对box数不指定,对任意box数实现动态布局;而grid布局需要指定行数,即box数为指定值。所以flex更支持一维场景下的动态配置。若box数为指定值,那可能使用grid和flex差别不大(作者暂未发现差别。不考虑底层实现差别,比如渲染方式等)。

其他对比

浏览器兼容性(chrome为例)

display:flex需要浏览器版本>=21,浏览器对flex属性支持较早,相对稳定;display:grid需要浏览器版本>=57,感觉支持程度也可以。

开发者熟悉程度

简单调研发现大部分前端开发者对flex比grid更熟悉一些。

小结

在一维布局的动态分配场景下,flex更灵活;动态指的是,比如box数不固定、内容决定box大小等。而在二维空间、布局决定盒子大小时,grid更具优势。2

在开发习惯上,一维场景下我们推荐使用flex布局,即便有些场景grid也可以实现;在二维场景下,我们推荐使用grid布局。

相关资料

[1]flex 布局的基本概念

[2]从内容出发还是从布局入手?

[3]利用 CSS 网格布局实现常用布局

[4]Flexbox 典型用例

附录

附录1

// html
<div class="container">
    <div>menu1</div>
    <div>menu2</div>
    <div>long menu3</div>
    <div class="right">icon1</div>
    <div>icon2</div>
</div>
​
// css
.container {
  display: flex;
  gap: 8px;
}
.right {
  margin-left: auto;
}
​
.container {
  width: 500px;
  border: 2px dotted rgb(96, 139, 168);
}
.container > * {
  padding: 0 8px;
  border: 2px solid rgb(96, 139, 168);
  border-radius: 5px;
  background-color: rgba(96, 139, 168, 0.2);
}

附录2

// html
<div>
    <div class="container">
      <div class="title">标题:配置logo</div>
      <div>
        <img src="//www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" width="200px">
      </div>
      <div>描述: 这是这个logo的详细描述,描述很长,可能占用很多行</div>
      <button>更新logo</button>
    </div>
</div>
​
// css
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.container > div {
  flex: 1 1 auto;
}
​
.title {
  align-self: start;
  font-weight: bold;
  font-size: 18px;
}
.container {
  width: 200px;
  height: 300px;
  padding: 8px;
  border: 2px dotted rgb(96, 139, 168);
}
button {
  width: 80px;
  border: 2px solid rgb(96, 139, 168);
  border-radius: 5px;
  background-color: rgba(96, 139, 168, 0.2);
}

附录3

// html
<div class="container">
    <div>One</div>
    <div>Two</div>
    <div>Three</div>
    <div>Four</div>
    <div>Five</div>
 </div>
 
// css
.container {
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(3, 1fr);
}
​
.container {
  width: 500px;
  border: 2px dotted rgb(96, 139, 168);
}
.container > * {
  height: 50px;
  border: 2px solid rgb(96, 139, 168);
  border-radius: 5px;
  background-color: rgba(96, 139, 168, 0.2);
}

附录4

// html
<div class="container">
    <div>One</div>
    <div>Two</div>
    <div>Three</div>
    <div>Four</div>
    <div>Five</div>
</div>
​
// css
.container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.container > * {
  flex: 1 1 150px;
}
.container::after {
  content: '';
  flex: 1 1 150px;
}
​
.container {
  width: 500px;
  border: 2px dotted rgb(96, 139, 168);
}
.container > * {
  height: 50px;
  border: 2px solid rgb(96, 139, 168);
  border-radius: 5px;
  background-color: rgba(96, 139, 168, 0.2);
}

附录5

// html
<div class="container">
    <div>One</div>
    <div>Two</div>
    <div>Three <br />has <br />extra <br />text</div>
</div>
​
​
// css
/* 方式一:flex布局 */
.container {
  display: flex;
  gap: 8px;
}
.container > * {
  flex-grow: 1
}
​
/* 方式二:grid布局*/
/* .container {
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(3, 1fr);
} */.container {
  width: 500px;
  border: 2px dotted rgb(96, 139, 168);
}
.container > * {
  border: 2px solid rgb(96, 139, 168);
  border-radius: 5px;
  background-color: rgba(96, 139, 168, 0.2);
}