· 3 min read
Flexbox:flex-grow 与 flex-shrink
CSS
给三个子元素设置 flex: 1,结果它们并没有等宽分空间。或者在窄屏幕上,某个重要按钮被挤压得看不见了。这些问题都和 flex-grow、flex-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>
避坑
-
flex-basis的优先级.item { width: 100px; flex-basis: 200px; /* 实际生效的是 200px */ } -
内容超出会溢出
.item { flex-shrink: 0; /* 设为 0 防止被压缩 */ overflow: hidden; /* 溢出隐藏 */ } -
flex: 1 vs flex: auto
/* flex: 1 - 基准值是 0%,会压到最小内容宽度 */ /* flex: auto - 基准值是元素内容,会保留内容宽度 */
总结
flex-grow:容器有剩 → 怎么分flex-shrink:容器不够 → 怎么缩- 常用组合:
flex: 1平均分、flex: 0 0 固定值固定宽
一个原则:想让元素灵活伸缩用
flex: 1,想保持固定用flex-shrink: 0。