visibility: hidden 隐藏元素但保留布局空间,子元素默认继承隐藏,不触发重排仅重绘,仍可被焦点和脚本访问,适合频繁切换场景;与 display: none 的核心区别在于是否保留文档流位置。

visibility: hidden 会让元素消失但保留布局空间
它不是删除元素,而是告诉浏览器“这个元素还在,只是别画出来”。父元素设置 visibility: hidden 时,子元素也会不可见(除非显式设为 visible),这点和 display: none 不同。
常见错误是以为它能“隐藏又不影响交互”——其实鼠标事件仍会穿透(比如点击不到背后的按钮),但焦点、键盘导航仍可能落在该元素上(尤其表单控件),导致可访问性问题。
- 适合需要临时隐藏、且后续频繁切换显示/隐藏的场景(比如折叠面板的过渡态)
- 动画中配合
visibility+opacity可避免重排,比单纯用opacity: 0更稳妥(后者仍响应事件) - 注意:IE8+ 支持,但早期安卓 WebView 有渲染残留 bug,需加
backface-visibility: hidden强制重绘
visibility: hidden 和 display: none 的关键区别
最直接的判断方式:打开浏览器开发者工具,看元素在 DOM 树里是否还“撑开”了空白区域。如果空白还在,就是 visibility: hidden;如果整个位置塌陷了,就是 display: none。
性能上,visibility: hidden 触发重绘(repaint),不触发重排(reflow);display: none 两者都触发,但首次隐藏开销更大。
-
visibility: hidden下的<input>仍可被focus()调用,也会计入document.querySelectorAll('input')结果 -
display: none下的元素完全脱离渲染树,getBoundingClientRect()返回全 0,offsetHeight为 0 - 用 JS 切换时,
visibility的 CSS 动画可用transition: visibility 0.1s(但必须搭配opacity才有渐变效果)
visibility: hidden 不生效?检查这几点
最常踩的坑是父元素已经设了 visibility: hidden,又给子元素设 visibility: visible,结果发现还是看不见——其实是父元素的隐藏优先级更高,子元素无法“逆向穿透”。
- 确认没有更上级的祖先元素也设置了
visibility: hidden - 检查是否被
opacity: 0或transform: scale(0)覆盖,CSS 层叠顺序会影响最终效果 - 某些 CSS 框架(如 Bootstrap)的
.invisible类实际用的是visibility: hidden,但可能带 !important,覆盖了你的样式 - 如果元素是
<canvas></canvas>或<video></video>,部分浏览器在visibility: hidden下仍会持续解码或渲染,造成 CPU 占用偏高
替代方案:何时该选 opacity: 0 而不是 visibility: hidden
当你要隐藏元素但希望它仍能响应点击、保持焦点能力(比如悬浮提示层的占位),opacity: 0 更合适;但它会参与事件捕获,可能挡住后面元素,得配 pointer-events: none。
而 visibility: hidden 天然不响应鼠标事件(pointer-events 默认为 auto,但不可见即无 hit-test),更适合“彻底静默”的隐藏需求。
-
opacity: 0触发重绘,支持硬件加速(加will-change: opacity),动画更流畅 -
visibility: hidden在 SVG 中行为一致,opacity: 0对<text></text>等元素有时有渲染差异 - 服务端渲染(SSR)页面中,若初始状态是隐藏,用
visibility: hidden可避免闪动(opacity从 1→0 会有瞬时可见)
真正麻烦的是混合使用:比如用 JS 控制 visibility 切换,又同时加了 transition: opacity,结果 visibility 立即生效,opacity 还在动,中间出现“半透明+可点”的诡异状态。这种细节,不调试根本看不出。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











