display: none 彻底移除元素,不占空间、触发重排、无障碍友好;visibility: hidden 保留占位、仅重绘、子元素可单独显示;二者均不响应鼠标事件,但 pointer-events 设置才决定事件穿透。

display: none 会让元素彻底退出文档流
设置 display: none 后,元素不仅不可见,而且不占任何空间,其后续兄弟元素会立即上移填补空位。浏览器渲染时完全跳过该元素的布局计算。
- 适用于需要「永久隐藏」或「条件性移除」的场景,比如切换菜单、表单步骤控制
- JavaScript 中读取
offsetHeight或getBoundingClientRect()会返回0 - 屏幕阅读器默认忽略
display: none元素,无障碍支持较好 - 触发重排(reflow)——因为布局结构实际发生了变化
visibility: hidden 保留占位但隐藏内容
visibility: hidden 只让元素变透明不可见,它在文档流中的位置、尺寸、边距都照常保留,周围元素不会移动。
- 适合做「临时遮罩」或「悬停过渡」,比如 tooltip 出现前先预占位
- 子元素可通过设置
visibility: visible单独显示(这是和opacity: 0的关键区别) - 仍可被 JavaScript 获取尺寸,
offsetHeight返回真实值 - 只触发重绘(repaint),不触发重排,性能略优
它们都不影响事件捕获和冒泡行为
两者都会让元素无法响应鼠标事件(如 click、hover),但事件仍可能穿透到下层元素——这取决于 pointer-events 设置,而非 visibility 或 display 本身。
-
display: none元素完全从事件系统中移除,其上的事件监听器不会触发 -
visibility: hidden元素虽不可见,但若设pointer-events: auto(默认),鼠标事件仍会被捕获(不过用户看不到反馈) - 更安全的做法是:隐藏同时加
pointer-events: none,避免意外触发
别用 opacity: 0 替代它们来“隐藏”
opacity: 0 是视觉透明,元素依然参与布局、响应事件、影响 z-index 层叠,和前两者有本质区别。
立即学习“前端免费学习笔记(深入)”;
button {
opacity: 0; /* 看不见,但能点中,占据空间,会挡住后面元素 */
/* 如果真想隐藏又保留结构,用 visibility: hidden 更准确 */
}真正需要「渐隐动画」时才用 opacity;纯隐藏逻辑,请优先选 display 或 visibility,并明确你是否要保留占位。
最易被忽略的一点:display 切换可能引发 layout thrashing,尤其在循环中反复读写 offsetHeight 再设 display;visibility 则相对温和——但如果你忘了子元素的 visibility 继承行为,反而会暴露本该隐藏的内容。










