css
// css
body {
display: flex;
width: 100px;
height: 100px;
}
.par {
flex: 1;
background-color: red;
}
.chi {
width: 100%;
height: 100%;
}
.demo {
width: 200px;
height: 200px;
}
// html
<body>
<div class="par">
<div class="chi">
<div class="demo"></div>
</div>
</div>
</body>
这段代码会看到这样子的效果:

要知道,红色背景的盒子只有 .par,body 设置为宽100,高100,.par 设置为 flex: 1应该默认也是宽100,高100,为什么会变成宽200,高100呢?
首先 .par 是一个 flex 项目,有主轴和侧轴,
在主轴方向上 ,.par 作为唯一的 Flex 项,会尝试填满主轴的剩余空间,但 flex 项目会默认设置 min-width: auto 会强制其宽度不小于内容的最小宽度 (即子元素 .chi 的宽度),其实 flex 项目也会设置 min-height: auto,但这其实影响不大。
在侧轴方向上 ,默认会被拉伸 (align-items: stretch),.par 的高度直接确定为父容器 body 的100。
以上结论可以通过给 body 添加 flex-direction: column; 得到验证,此时主轴是从上往下,侧轴是从左往右,.par 元素的 min-height 会被设置为 auto,同时侧轴会因为默认的 align-items: stretch 被拉伸,也就是最终会看到一个宽100,高200的长方形,效果如下:

结论完全正确。
那已经知道问题在哪里了,要怎么让 .par 和 body 保持一样的宽高呢?.par 的宽度和高度被拉伸主要是因为 min-height: auto 和 min-width: auto,只需要为 .par 设置 min-height: 0 和 min-width: 0 覆盖掉默认的 min-height: auto 和 min-width: auto 就行。最终效果:

让我们再深入一些,为什么一开始 .par 会受到深层嵌套的 .demo 元素的宽200影响,浏览器是怎么确定 .par 的宽度的?这涉及 浏览器渲染引擎的布局计算机制,尤其是嵌套元素尺寸的递归解析过程。以下通过分步拆解和类比,解释这一过程:
一、核心问题:深层嵌套元素的宽度如何影响祖先?
在例子中:
scss
.par (Flex项) → .chi (width: 100%) → .demo (width: 200px)
问题本质是: .demo 的宽度会逐层向上影响 .chi 和 .par 的宽度吗?浏览器是否需要等待所有子元素计算完毕才能确定父元素尺寸?
答案是 Yes ,但浏览器通过 递归计算 和 多趟布局(Layout Passes) 高效解决这一问题。
二、浏览器布局计算的步骤
1. 初始布局阶段(First Layout Pass)
-
方向:自顶向下(从根元素到深层子元素)。
-
行为:
- 浏览器先假设
.par的宽度为父容器(body)的100px(因为flex:1)。 .chi的width: 100%继承.par的初始宽度100px。.demo的width: 200px直接应用,此时.demo的实际宽度为200px。
- 浏览器先假设
-
矛盾出现 :
.chi的内容宽度(.demo的200px)超出了其自身的100px,导致.chi的 内容溢出。
2. 回撤与修正(Backtracking)
-
方向:自底向上(从子元素到祖先)。
-
行为:
- 浏览器发现
.chi的内容宽度(200px)超出了其自身的100px。 - 由于
.par是 Flex 项且默认min-width: auto,它必须至少与子元素的最小宽度一致(200px)。 - 浏览器重新计算
.par的宽度为200px,并向上修正父容器body的布局(尽管body显式设置了width: 100px,但默认允许溢出)。
- 浏览器发现
3. 最终布局结果
| 元素 | 初始宽度 | 修正后宽度 | 原因 |
|---|---|---|---|
body |
100px | 100px | 显式设置,但允许内容溢出 |
.par |
100px | 200px | min-width: auto 被内容撑开 |
.chi |
100px | 200px | 继承 .par 的修正后宽度 |
.demo |
200px | 200px | 显式设置 |