深入解析 flex: 1 1 0%
的底层逻辑(含实战对照)
一、属性拆解与核心公式
/* 完整写法 */
flex-grow: 1; /* 放大系数 */
flex-shrink: 1; /* 缩小系数 */
flex-basis: 0%; /* 基准尺寸 */
空间分配公式
可用空间 = 容器宽度 - 所有项目的总基准宽度
- 正值 → 按
flex-grow
比例分配剩余空间 - 负值 → 按
flex-shrink × basis
比例压缩
二、关键实验(通过案例理解本质)
实验1:基准尺寸对比
<div class="container">
<div class="item">内容较长的项目</div>
<div class="item">短</div>
</div>
场景A:flex: 1 1 auto
.container { display: flex; width: 600px; }
.item { flex: 1 1 auto; }
- 结果:项目宽度基于内容自然宽度,无法均分容器
- 计算:
- 项目1自然宽度300px,项目2自然宽度100px
- 剩余空间 = 600 - (300+100) = 200px
- 项目1获得 200×(1/2)=100px → 总宽400px
- 项目2获得 200×(1/2)=100px → 总宽200px
场景B:flex: 1 1 0%
.item { flex: 1 1 0%; }
- 结果:完全忽略内容宽度,严格按比例分配
- 计算:
- 基准宽度总和 = 0% + 0% = 0px
- 剩余空间 = 600 - 0 = 600px
- 均分空间 → 各占300px
实验2:不同flex值的对比
<div class="container">
<div class="itemA">A</div>
<div class="itemB">B</div>
</div>
.container { display: flex; width: 1000px; }
配置1:itemA: flex: 2 1 0%
,itemB: flex: 1 1 0%
- 计算:
- 总系数 = 2 + 1 = 3
- A宽度 = 1000 × (2/3) ≈ 666.67px
- B宽度 = 1000 × (1/3) ≈ 333.33px
配置2:itemA: flex: 1 1 200px
,itemB: flex: 2 1 100px
- 计算:
- 基准总和 = 200 + 100 = 300px
- 剩余空间 = 1000 - 300 = 700px
- A获得:700 × (1/(1+2)) ≈ 233.33px → 总宽433.33px
- B获得:700 × (2/3) ≈ 466.67px → 总宽566.67px
三、flex-basis的特殊模式
1. 0%
vs auto
核心区别
场景 | 0% | auto |
---|---|---|
初始宽度 | 0 | 内容自然宽度 |
空间分配 | 完全按系数分配 | 受内容影响 |
兼容性 | 需要-webkit前缀(旧浏览器) | 全兼容 |
典型应用 | 严格比例布局 | 内容优先布局 |
2. 浏览器渲染步骤
- 计算所有项目的基准尺寸总和
- 判断可用空间正负
- 按
flex-grow
/flex-shrink
分配空间 - 最终尺寸 = basis + 分配到的空间
四、实战应用场景
场景1:等高三栏布局
.container {
display: flex;
align-items: stretch; /* 默认值 */
}
.sidebar {
flex: 0 0 200px; /* 固定宽度 */
}
.main {
flex: 1 1 0%; /* 占据剩余空间 */
}
场景2:动态输入框布局
<div class="search-bar">
<input type="text" style="flex:3 1 0%">
<button style="flex:1 1 0%">搜索</button>
</div>
- 输入框与按钮保持3:1宽度比
场景3:瀑布流布局
.card {
flex: 1 1 300px; /* 基础300px,可伸缩 */
max-width: 400px; /* 防止过度放大 */
}
五、调试技巧
-
Chrome DevTools 可视化:
- 开启Flexbox overlay(显示flex线)
- 查看Computed面板中的最终尺寸
-
边界测试:
/* 测试是否可缩小 */ .item { flex-shrink: 0; /* 禁止缩小 */ background: red !important; /* 高亮异常项 */ }
-
最小内容宽度保护:
.item { min-width: min-content; /* 防止内容被挤压 */ }