display: none 是唯一真正移除渲染的方式,它让元素彻底退出渲染树、不占空间、不响应事件,offsetheight 和 getboundingclientrect() 返回全为 0,适合权限控制、弹窗关闭等“该区域不该存在”的场景。

display: none 是唯一真正移除渲染的方式
它让元素彻底退出渲染树,不占空间、不响应事件,offsetHeight 和 getBoundingClientRect() 返回全为 0。适合权限控制、弹窗关闭、条件渲染等“该区域不该存在”的场景。
常见错误现象:v-if 和 {condition && <div>} 底层就是靠这个机制,但有人误用 <code>visibility: hidden 替代,结果 tab 键还能聚焦到空白处,布局也塌不了。
-
display: none会触发重排(reflow),动画中频繁切换影响性能 - 内联样式优先级高于
hidden属性,比如<div hidden style="display: block">,<code>hidden就失效了 - 子元素无论设
display: block都无效——父级已斩断渲染链 - 支持
transition,但只对visible → hidden有延迟效果;反向切换无过渡 - 搭配
opacity: 0做淡出更稳妥,但得手动加pointer-events: none防点击穿透 - IE8+ 全兼容,但对屏幕阅读器不一定静默(取决于 UA 实现)
- 必须三件套齐上:
opacity: 0+pointer-events: none+tabindex="-1" - 和
transition: opacity 0.3s天然契合,比display切换流畅得多 - 只触发重绘(repaint),不触发重排(reflow),性能影响小
- 别混用:
hidden和style="display: none"同时存在时,后者优先级更高 - 服务端渲染时,
hidden属性比 CSS 更早生效,避免 FOUC(闪现) - 使用场景很窄:适合服务端渲染后、JS 尚未加载时的“默认隐藏”,或配合 Web Component 的生命周期做状态同步
visibility: hidden 保留占位且子元素可“钻出来”
它只是视觉隐藏,元素仍在文档流里,父容器高度不会塌缩,tabindex 仍生效。关键区别在于:子元素设 visibility: visible 能强行显示,而 display: none 下做不到。
典型翻车点:表单里用它隐藏 <input>,用户按 Tab 键仍会聚焦到空白位置,体验断裂。
opacity: 0 不等于隐藏,必须配对禁用交互
opacity: 0 只是透明,元素几何信息、事件监听、焦点能力全部保留。很多所谓“隐藏”需求其实要的是“不可见且不可交互”,漏掉 pointer-events: none 和 tabindex="-1" 就会出问题。
典型错误现象:轮播图切换时用 opacity: 0 隐藏旧图,用户手快连点两下,触发两次回调——因为元素还在监听 click。
hidden 属性语义化强但易被 CSS 覆盖
hidden 是 HTML5 原生布尔属性,等价于 display: none,但带语义优势:对屏幕阅读器明确传达“此内容当前不相关”。JS 操作也轻量:el.hidden = true 不触发布局计算。
但它不是万能开关——CSS 里一条 [hidden] { display: block; } 就能让它失效。Vue/React 中直接写 hidden={condition} 是安全的,但 Svelte 需配合 class:hidden={condition}。
tabindex="-1",键盘用户就会卡在看不见的控件上。











