display: none 使元素彻底消失且不占空间,触发重排;visibility: hidden 仅隐藏但保留布局,只触发重绘;二者同时设置时 display 优先;pointer-events: none 才禁用交互。

display: none 会让元素彻底“消失”
它不只是看不见,而是从渲染树里被拿掉——不占空间、不参与布局、后续元素会立刻补位。JavaScript 读 offsetHeight 或 getBoundingClientRect() 都返回 0,display: none 的元素也完全不响应鼠标事件(哪怕绑了 click 监听器也不会触发)。
常见错误:在循环中反复读取 offsetHeight 再设 display: none,容易引发 layout thrashing;用它做动画过渡会导致跳变,因为布局瞬间重排。
- 适用场景:弹窗关闭后彻底移除、表单步骤切换、条件性隐藏整块区域
- 无障碍友好:
screen reader默认跳过display: none元素 - 性能影响:触发 reflow(重排),开销比
visibility: hidden大
visibility: hidden 只是“看不见”,但还在原位
元素仍保留在文档流中,宽高、margin、padding 全部照常计算,周围元素不动。子元素可以通过显式设置 visibility: visible 单独显示出来——这是和 display: none 最关键的株连性差异。
常见错误:忘了子元素继承 visibility: hidden,结果父层隐藏了,但某个子节点意外加了 visibility: visible,内容就漏出来了。
立即学习“前端免费学习笔记(深入)”;
- 适用场景:下拉菜单展开前预占位、tooltip 悬停过渡、需要保留布局稳定的临时遮罩
- 尺寸可读:
offsetHeight返回真实值,适合依赖尺寸的 JS 逻辑 - 性能影响:只触发 repaint(重绘),不触发 reflow
两者同时设置时,display 优先级更高
如果一个元素同时写了 display: none 和 visibility: visible,它依然不会显示、不占空间——display 决定“是否存在”,visibility 只管“是否看得见”,前者胜出。
实际中极少需要同时写,但要注意 CSS 优先级或 JS 动态设置时可能意外叠加。比如用 JS 先设 element.style.visibility = 'hidden',再设 element.style.display = 'none',后者生效;反过来则可能被覆盖。
- 别用
opacity: 0替代它们:它既占位又响应事件,语义完全不同 - 想做渐隐动画?用
opacity+visibility配合transition;纯显隐控制,选display或visibility,看你要不要留空位
pointer-events 不是 visibility 或 display 的一部分
很多人以为 visibility: hidden 或 display: none 能控制鼠标穿透,其实不能。pointer-events: none 才真正禁用交互;而 visibility: hidden 元素默认仍捕获事件(只是用户看不到反馈),display: none 则完全脱离事件系统。
容易踩坑:只设 visibility: hidden 就以为按钮点不了,结果用户一不小心还是触发了 click——得额外加 pointer-events: none 才保险。
- 安全做法:隐藏 + 禁交互,组合使用
visibility: hidden和pointer-events: none - 别依赖继承:
pointer-events不继承,子元素需单独设置
display 会清空一切布局上下文,而 visibility 的继承行为会让子元素“偷偷露头”。写完记得检查 DOM 结构和事件响应,尤其在动态渲染场景里。


















