本质区别在于:display: none让元素彻底退出渲染树,不参与布局、不占空间、不响应交互;visibility: hidden仅视觉隐藏,元素仍在文档流中,保留尺寸、位置和事件捕获路径。

本质区别在于:display: none让元素彻底退出渲染树,不参与布局、不占空间、不响应任何交互;visibility: hidden只是“盖住”元素,它仍在文档流中,尺寸、位置、事件捕获路径都完整保留。
display: none 会触发重排,且 DOM 尺寸读取全为 0
设 display: none 后,浏览器在布局阶段就跳过该元素:没有盒模型、没有 offsetParent、offsetHeight 和 getBoundingClientRect() 全返回 0。后续兄弟元素立刻上移补位,页面发生重排(reflow)。
- 常见错误:在循环中反复
el.style.display = 'none'后立刻读取offsetHeight,强制同步重排,造成 layout thrashing - Canvas 父容器设
display: none再显示,可能空白——canvas 渲染上下文被丢弃;visibility: hidden不影响上下文 - 表单中
<input name="email">设display: none后不会随表单提交;设visibility: hidden仍会提交
visibility: hidden 是继承属性,子元素可穿透显示
visibility 具有继承性,父级设 visibility: hidden,子元素默认也隐藏;但只要显式设 visibility: visible,就能单独显示出来——这是 display: none 完全做不到的。
- 适用场景:tooltip 预占位容器、带图标按钮的禁用态(图标可见)、状态徽章叠加
- 注意:子元素即使
visibility: visible,默认仍不响应鼠标事件,需额外加pointer-events: auto - 表格行
<tr> 设 <code>visibility: hidden,部分浏览器下<tbody> 高度计算异常,建议改用 <code>display: none或外层包裹<div> <h3>无障碍与事件行为完全不同</h3> <p><code>display: none的元素对屏幕阅读器完全不可见,也不在焦点流中,focus()失败,click事件根本不会触发;而visibility: hidden的<input>仍能被focus()调用(光标看不见),事件也能捕获到(只是用户看不到反馈)。立即学习“前端免费学习笔记(深入)”;
- 权限控制或 Tab 切换时,必须用
display: none防止键盘用户意外聚焦到隐藏区域 - 若用
visibility: hidden隐藏敏感内容,需手动加aria-hidden="true",否则屏幕阅读器仍会朗读 - 打印样式表中:
display: none真正不打印,visibility: hidden仍会出现在打印输出里
真正难的不是记清区别,而是每次写
style.display = 'none'或style.visibility = 'hidden'前,先问自己一句:你到底想“删掉它”,还是“盖住它但留着锚点”?选错一个,后面调试布局抖动、事件穿透、Canvas 白屏的时间,远比多敲两个字符贵得多。 - 权限控制或 Tab 切换时,必须用


















