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 | 显式设置 |