根本原因是浮动元素与相对定位元素分属不同渲染层,z-index对未定位浮动元素无效;应通过clear:both避让或触发BFC(如overflow:auto、display:flow-root)收束浮动。

浮动元素遮挡下方 position: relative 元素,根本不是 z-index 没设够,而是渲染层归属错位——浮动在「浮动层」,相对定位元素默认升到「定位层」,天然压它一头。
为什么给浮动元素加 z-index 无效
因为 z-index 只对已定位元素生效,而纯 float: left 或 float: right 的元素不属于定位元素,也不创建层叠上下文。你写 z-index: 999 完全被浏览器忽略,Computed 面板里显示的仍是 auto。
- 只有同时加上
position: relative(或absolute/fixed)后,z-index才开始起作用 - 但此时它进入的是新层叠上下文,层级比较范围受限于其最近的「已定位且创建层叠上下文」祖先
- 如果父容器有
transform、opacity: 0.99或will-change,那这个新上下文就锁死在内部,再高的z-index也出不来
真正该用 clear 的地方:让相对定位元素主动避让
浮动元素占据的是行内空间,后续块级元素(比如那个 position: relative 的 div)默认会尝试“绕流”——结果就是视觉上重叠、点击失效、文字被盖住。
- 给那个相对定位元素直接加
clear: both,它就会强制下移到浮动区域下方,不再争夺同一行 - 如果它本身是
display: inline-block或float,先确保它恢复为display: block再加clear - 别只清最外层——嵌套浮动时,每个需要避开浮动的兄弟容器都得单独加
clear,否则漏一个,后面全乱
更干净的解法:用 BFC 收束浮动,而不是靠 clear 补漏
与其让每个后续元素都手动避让,不如让浮动“待在自己家”。给浮动元素的父容器触发 BFC,它就能包裹住子浮动,不干扰外部布局。
立即学习“前端免费学习笔记(深入)”;
- 推荐写法:
overflow: auto(比hidden安全,不裁剪溢出内容) - 现代标准写法:
display: flow-root(无副作用,语义清晰,但 IE 不支持) - 伪元素清除(
::after)适合兼容老项目,但必须保证三件套齐全:content: ""+display: table(或block)+clear: both - 避免在父容器上误加
overflow: hidden——如果它里面还有position: absolute下拉菜单,会被直接裁掉
检查是否真被遮挡:别信眼睛,看层和盒模型
你以为是遮挡,实际可能是盒模型偏移、高度塌陷,或者事件被拦截。调试时盯紧两个地方:
- 用 DevTools 查目标元素的
getBoundingClientRect(),对比返回坐标和你鼠标点击位置是否一致 - 打开 Rendering → 勾选
Show layer borders,确认浮动元素和相对定位元素是否真的分属不同渲染层 - 检查父容器 computed height 是否为 0 —— 是的话,问题根源是塌陷,不是遮挡;不是的话,再查层叠上下文是否被意外创建
浮动的“传染性”极强,一个没清干净,后面一串布局都会错位。别指望靠 z-index 打补丁,该触发 BFC 的地方触发,该加 clear 的地方加,才是稳的。


















