浮动元素不创建层叠上下文,z-index无效;而position: relative元素默认进入第6层叠等级,天然高于浮动元素的第4级;混用float与position: relative时z-index才生效,但起效的是定位属性而非浮动。

浮动元素根本不创建层叠上下文
这是最根本的原因:float 是布局行为,不是定位模式。浏览器在构建层叠上下文(stacking context)时,只认 position 值为 relative、absolute、fixed 或 sticky 的元素——float: left 或 float: right 不在此列。哪怕你写了 z-index: 999,只要没加 position,这个 z-index 就被静默忽略。
所以“浮动元素层叠上下文低于相对定位”这个说法本身不严谨:浮动元素压根没有自己的层叠上下文;而 position: relative 元素,只要设置了 z-index(哪怕是 0),就自动创建了一个新的层叠上下文——它天然比“无上下文”的浮动元素层级高。
相对定位元素默认进入更高层叠等级
根据 CSS 层叠顺序规则,在同一个根上下文中:
-
float元素属于第 4 级(“浮动元素”层) - 未设
z-index的position: relative元素属于第 6 级(z-index: auto或0的定位元素) - 设置了正
z-index的定位元素则进入第 7 级(更高)
也就是说,哪怕你什么都没写,一个空的 .box { position: relative; } 就已经比 .float-box { float: left; } 在渲染时“画得更晚、盖得更上”。这不是 z-index 数值决定的,而是层叠等级(stacking level)的硬性排序。
立即学习“前端免费学习笔记(深入)”;
混用 float 和 position: relative 时 z-index 才真正生效
很多人误以为“给浮动元素加了 z-index 就行”,其实关键在 position:
- 错误写法:
.box { float: left; z-index: 10; }→z-index无效 - 正确写法:
.box { float: left; position: relative; z-index: 10; }→ 此时才触发定位,z-index开始参与比较
但注意:此时起效的不是“浮动”,而是 position: relative。浮动属性依然存在,但它对层叠已无影响;后续是否被盖住,完全取决于该元素所在层叠上下文中的 z-index 值和兄弟元素的上下文关系。
父容器无意中创建隔离层叠上下文
即使你给两个元素都加了 position: relative 和 z-index,它们仍可能无法按预期叠加——常见原因是父容器悄悄创建了新层叠上下文:
-
opacity: 0.99、transform: translateY(0)、filter: blur(0)、will-change: transform - 这些属性会让父容器变成独立层叠上下文,子元素的
z-index只在内部比较,不再和外部元素竞争 - 结果就是:浮动元素所在的父容器若带
opacity,它整个子树都被“锁”在底层;而相对定位元素若在另一个无干扰的父容器里,自然就浮上来了
这类问题很难肉眼识别,必须打开浏览器开发者工具的 “Layers” 面板或勾选 “Show layer borders” 才能验证实际层叠结构。


















