4、Flexbox弹性布局:Flex容器属性、Flex项目属性、常见布局模式、实战案例

Flexbox,说实话,是我日常开发中用得最多的布局方案。没有之一。

我记得刚入行那会儿,还在用float+clearfix那套老办法做导航栏,每次都要算宽度、清浮动,烦得很。后来接触了Flexbox,感觉整个世界都清爽了。你想想看,一行代码就能让子元素水平居中,这在以前得折腾多少东西?

好,咱们今天就把Flexbox彻底讲透。从容器属性到项目属性,再到常见的布局套路,最后带一个实战案例。我保证,学完这节课,你以后写页面布局会顺手很多。

4.1 Flex容器属性:掌控大局的指挥官

先搞清楚一个概念:Flex容器Flex项目。给一个元素设置 display: flex;,它就变成了容器,它的直接子元素自动成为项目。容器属性管的是「整体怎么排」,项目属性管的是「每个元素怎么站」。

4.1.1 flex-direction:主轴方向

这是最基础的属性。它决定了主轴的方向,也就是项目排列的走向。

  • row(默认):从左到右水平排列
  • row-reverse:从右到左水平排列
  • column:从上到下垂直排列
  • column-reverse:从下到上垂直排列

我的习惯:做导航栏、卡片列表用 row;做表单、纵向菜单用 column。别纠结,用多了自然就记住了。

4.1.2 flex-wrap:换行策略

项目太多,一行装不下怎么办?这个属性就是管这个的。

  • nowrap(默认):不换行,强行压缩项目宽度
  • wrap:换行,项目保持原尺寸
  • wrap-reverse:换行,但新行在上方

我曾经踩过的坑:做商品列表时,忘了设 flex-wrap: wrap;,结果所有商品挤在一行,图片都变形了。排查了半天才发现是默认不换行。嗯,这个坑你们别踩。

4.1.3 justify-content:主轴对齐

这个属性太常用了。它控制项目在主轴方向上的对齐方式。

效果
flex-start左对齐(默认)
flex-end右对齐
center居中
space-between两端对齐,项目之间间距相等
space-around每个项目两侧间距相等
space-evenly所有间距完全相等

我个人最常用的是 space-betweencenter。比如做导航栏,logo在左、菜单在右,用 space-between 一行代码搞定。

4.1.4 align-items:交叉轴对齐

主轴搞定了,交叉轴也得管。这个属性控制项目在交叉轴方向上的对齐。

  • stretch(默认):拉伸填满容器高度
  • flex-start:顶部对齐
  • flex-end:底部对齐
  • center:垂直居中
  • baseline:基线对齐

小技巧:想让一个盒子在页面正中间?display: flex; justify-content: center; align-items: center; 三行代码搞定。以前用绝对定位得算半天偏移量,现在多省事。

4.1.5 align-content:多行对齐

这个属性只有在 flex-wrap: wrap 且有多行时才生效。它控制整个「行组」在交叉轴上的对齐方式。取值跟 justify-content 类似,就不重复了。

4.2 Flex项目属性:每个元素的自我修养

容器属性管整体,项目属性管个体。每个项目都可以有自己的「想法」。

4.2.1 flex-grow:放大比例

默认是0,表示不放大。如果所有项目都设为1,它们会等分剩余空间。如果某个项目设为2,它占的空间是其他项目的两倍。

/* 左侧固定,右侧自适应 */
.left { flex-grow: 0; width: 200px; }
.right { flex-grow: 1; }

这个模式我几乎天天用。左侧导航栏固定宽度,右侧内容区自适应,完美。

4.2.2 flex-shrink:缩小比例

默认是1,表示空间不够时可以缩小。设为0表示打死也不缩小。

注意:如果所有项目都设了 flex-shrink: 0,而容器宽度不够,内容会溢出。我见过有人把每个项目都设成不缩小,结果页面出现了横向滚动条,用户体验很差。

4.2.3 flex-basis:初始尺寸

可以理解为项目在主轴方向上的「理想尺寸」。默认是 auto,即项目本身的宽或高。

4.2.4 flex:简写属性

推荐用这个简写,一行搞定三个属性:flex: grow shrink basis;

/* 常用写法 */
flex: 1;           /* 等价于 flex: 1 1 0% */
flex: auto;        /* 等价于 flex: 1 1 auto */
flex: none;        /* 等价于 flex: 0 0 auto */

我个人习惯用 flex: 1 做自适应布局,简洁明了。

4.2.5 align-self:个体对齐

覆盖容器的 align-items 设置。比如容器统一左对齐,但某个特殊项目想靠右,就用这个。

4.2.6 order:排列顺序

默认是0。数值越小越靠前。可以设为负数。

实战场景:移动端想把「提交按钮」放在表单最前面,但PC端想放最后。用 order 配合媒体查询,不用改HTML结构,爽得很。

4.3 常见布局模式:拿来即用的套路

下面这几个模式,是我这些年总结出来的高频场景。你直接复制代码改改就能用。

4.3.1 水平居中

.container {
  display: flex;
  justify-content: center;
}

4.3.2 垂直居中

.container {
  display: flex;
  align-items: center;
}

4.3.3 水平垂直居中

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

4.3.4 圣杯布局(两侧固定,中间自适应)

.container {
  display: flex;
}
.left { width: 200px; flex-shrink: 0; }
.right { width: 200px; flex-shrink: 0; }
.center { flex: 1; }

4.3.5 等分布局

.container {
  display: flex;
}
.item {
  flex: 1;
}

4.3.6 流式布局(自动换行)

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}
.item {
  width: calc(33.33% - 16px);
}

注意:gap 属性在Flexbox中已经得到广泛支持了。以前得用margin模拟间距,现在直接用 gap,干净利落。

4.4 实战案例:响应式导航栏 + 卡片列表

光说不练假把式。咱们来做一个完整的页面片段:顶部导航栏 + 下方商品卡片列表。

4.4.1 HTML结构

<nav class="navbar">
  <div class="logo">我的商店</div>
  <ul class="nav-links">
    <li>首页</li>
    <li>商品</li>
    <li>关于</li>
    <li>联系</li>
  </ul>
</nav>

<section class="card-list">
  <div class="card">商品1</div>
  <div class="card">商品2</div>
  <div class="card">商品3</div>
  <div class="card">商品4</div>
  <div class="card">商品5</div>
  <div class="card">商品6</div>
</section>

4.4.2 CSS样式

/* 导航栏 */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background: #f5f5f5;
}

.nav-links {
  display: flex;
  gap: 24px;
  list-style: none;
}

/* 卡片列表 */
.card-list {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  padding: 24px;
}

.card {
  flex: 1 1 calc(33.33% - 20px);
  min-width: 250px;
  padding: 40px;
  background: #fff;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  text-align: center;
}

/* 响应式:小屏幕变两列 */
@media (max-width: 768px) {
  .card {
    flex: 1 1 calc(50% - 20px);
  }
}

/* 响应式:手机屏幕变一列 */
@media (max-width: 480px) {
  .card {
    flex: 1 1 100%;
  }
}

我的经验:做响应式时,我习惯先写PC端样式,再用媒体查询向下兼容。但如果你做的是移动端优先的项目,反过来写也行。关键是保持一致性。

4.5 避坑指南

  • flex-basis 和 width 的关系:flex-direction: row 时,flex-basis 会覆盖 width。我刚开始学的时候被这个坑过。
  • min-width 的优先级:即使设了 flex-shrink: 1,项目也不会缩小到 min-width 以下。这是浏览器的保护机制。
  • 不要滥用 flex: 1:所有项目都设 flex: 1 确实能等分,但如果内容长短不一,视觉上可能不整齐。这时候用 flex: 1 1 0% 更稳妥。

好了,Flexbox的核心内容就这些。说实话,这个知识点不难,但需要多练。你可以在CodePen上随便拖几个盒子试试,玩熟了自然就记住了。下一节咱们聊Grid布局,那又是另一个世界了。