Back to Blog
· 3 min read

Flexbox:flex-grow 与 flex-shrink

CSS

给三个子元素设置 flex: 1,结果它们并没有等宽分空间。或者在窄屏幕上,某个重要按钮被挤压得看不见了。这些问题都和 flex-growflex-shrink 有关。

flex-grow:如何分配多余空间

当容器有剩余空间时,flex-grow 决定子元素如何”争抢”这些空间。

.container {
  display: flex;
  width: 500px;  /* 容器宽度 */
}

.item {
  width: 100px;  /* 每个元素基础宽度 */
}
/* 500 - 100*3 = 200px 剩余空间 */

核心规则

  • 默认值是 0,表示”不增长”
  • 值越大,分到的空间越多
  • 分配公式:自身份数 / 所有元素份数之和
/* 场景:容器 500px,三个子元素各 100px,剩余 200px */

.item1 { flex-grow: 1; }  /* 1/(1+2+3) = 1/6 * 200 = 33px */
.item2 { flex-grow: 2; }  /* 2/6 * 200 = 67px */
.item3 { flex-grow: 3; }  /* 3/6 * 200 = 100px */

/* 最终宽度:133px, 167px, 200px */

示例:圣杯布局

.header {
  flex-grow: 0;  /* 不增长 */
}

.content {
  flex-grow: 1;  /* 中间内容区占满剩余空间 */
}

.sidebar {
  flex-grow: 0;  /* 不增长 */
}
<nav class="header">Header</nav>
<main class="content">Main Content</main>
<aside class="sidebar">Sidebar</aside>

flex-shrink:空间不足时如何收缩

当容器空间不够时,flex-shrink 决定谁”牺牲”更多。

.container {
  display: flex;
  width: 300px;  /* 容器宽度 */
}

.item {
  width: 150px;  /* 每个元素基础宽度 */
}
/* 150*3 = 450px > 300px,需要收缩 150px */

核心规则

  • 默认值是 1,表示”可以收缩”
  • 设为 0 表示”绝不收缩”
  • 值越大,收缩得越多
/* 场景:容器 300px,三个子元素各 150px,超出 150px */

.item1 { flex-shrink: 1; }  /* 收缩 30px */
.item2 { flex-shrink: 2; }  /* 收缩 60px */
.item3 { flex-shrink: 0; }  /* 不收缩 */

/* 收缩计算:150 / (1+2+0) = 50px 每份 */

场景:防止关键内容被压缩

.button-primary {
  flex-shrink: 0;  /* 按钮不收缩,保证可点击 */
  padding: 12px 24px;
  background: #0070f3;
  color: white;
  border-radius: 6px;
}

.text-content {
  flex-shrink: 1;  /* 文字区域可以收缩 */
}
<div class="card">
  <span class="text-content">很长的文字内容...</span>
  <button class="button-primary">提交</button>
</div>

flex 缩写

日常开发中,通常用 flex 简写:

/* flex: <flex-grow> <flex-shrink> <flex-basis> */

flex: 1;        /* 1 1 0% - 平均分配空间 */
flex: 1 0;      /* 1 0 0% - 只增长不收缩 */
flex: 0 1 auto; /* 0 1 auto - 默认值,等价于 0 1 auto */
flex: auto;     /* 1 1 auto - 可增长可收缩 */
flex: none;     /* 0 0 auto - 不增长不收缩 */

常见组合及适用场景

写法效果适用场景
flex: 1平均分配导航菜单、等宽卡片
flex: 0 0 200px固定宽度侧边栏、固定宽度列
flex: auto自适应内容可长可短的布局
flex: none固定尺寸按钮、图标等

完整示例:三栏布局

.layout {
  display: flex;
  height: 100vh;
}

.sidebar-left {
  width: 200px;
  flex-shrink: 0;  /* 固定宽度不收缩 */
}

.content {
  flex: 1;         /* 占据剩余空间 */
}

.sidebar-right {
  width: 200px;
  flex-shrink: 0;
}
<div class="layout">
  <aside class="sidebar-left">左侧边栏</aside>
  <main class="content">主内容区</main>
  <aside class="sidebar-right">右侧边栏</aside>
</div>

避坑

  1. flex-basis 的优先级

    .item {
      width: 100px;
      flex-basis: 200px;  /* 实际生效的是 200px */
    }
  2. 内容超出会溢出

    .item {
      flex-shrink: 0;  /* 设为 0 防止被压缩 */
      overflow: hidden; /* 溢出隐藏 */
    }
  3. flex: 1 vs flex: auto

    /* flex: 1 - 基准值是 0%,会压到最小内容宽度 */
    /* flex: auto - 基准值是元素内容,会保留内容宽度 */

总结

  • flex-grow:容器有剩 → 怎么分
  • flex-shrink:容器不够 → 怎么缩
  • 常用组合flex: 1 平均分、flex: 0 0 固定值 固定宽

一个原则:想让元素灵活伸缩用 flex: 1,想保持固定用 flex-shrink: 0


相关阅读