visibility: hidden 是最稳妥的占位隐藏方案,因它保持盒模型、不触发重排、支持精确尺寸获取,且z-index行为干净;但具强制继承性,不支持transition,需额外处理焦点和可访问性。

visibility: hidden 和 opacity: 0 都保留 DOM 占位,display: none 不保留。
为什么 visibility: hidden 是最稳妥的占位隐藏方案
它让元素“闭眼站原地”:盒模型照常计算,offsetHeight、getBoundingClientRect() 返回真实值,不会触发重排(reflow),只触发重绘(repaint)。适合轮播图预加载、表单错误提示占位、Canvas 容器隐藏等对布局稳定性要求高的场景。
需要注意:visibility 具有强制继承性——父元素设了 visibility: hidden,子元素即使写 visibility: visible,只要中间某层祖先也设了 hidden,它就不可见。这不是样式没生效,是渲染引擎规则。
- 不支持
transition: visibility,浏览器直接忽略 - 默认仍响应键盘焦点(如
Tab切入<input>),需加pointer-events: none禁鼠标,aria-hidden="true"控制读屏器 - 不会创建新层叠上下文,
z-index行为干净
opacity: 0 虽然占位但容易引发 z-index 和事件问题
它把元素变透明,但依然参与事件捕获和层叠上下文创建。常见坑包括:
- 父容器
opacity: 0后,子元素即使opacity: 1也无效(继承不可逆) - 会强制创建新的层叠上下文,可能使
z-index行为偏离预期,尤其在模态框、下拉菜单中易出错 - 默认仍响应
click、hover,必须手动加pointer-events: none才能禁交互 - 适合需要淡入淡出动画的场景,但若只是静态隐藏,不如
visibility: hidden直接
display: none 彻底移出文档流,不是“隐藏”而是“删除视觉呈现”
它会让元素从渲染树中消失,带来一连串连锁反应:
-
offsetParent返回null,getClientRects()返回空集合,JS 尺寸判断逻辑容易崩 - Canvas / Video 元素可能被清空上下文或中断解码
- 屏幕阅读器默认跳过,无障碍支持弱,需额外补
aria-hidden="false" - 频繁切换会反复触发重排,性能开销明显高于另两者
visibility: hidden 下的 <input> 仍能被 focus()、仍出现在 document.querySelectorAll('input') 结果里;而 opacity: 0 的按钮点击区域还在,但用户看不见,极易造成误操作。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











