display: none 和 visibility: hidden 均不移除 DOM 节点,但 display: none 使元素脱离文档流、不占空间、不参与布局与绘制,visibility: hidden 则保留在文档流中、占位、参与布局但仅隐藏渲染。

使用 display: none 和 visibility: hidden 隐藏 DOM 元素时,元素在 DOM 节点层面都依然存在,但它们对节点“参与渲染与布局”的状态有本质差异。
display: none —— 节点脱离文档流,不参与布局计算
元素的 DOM 节点仍在内存中、仍可通过 JavaScript 访问(如 document.getElementById),但它:
- 不占据任何物理空间,
offsetTop、offsetHeight、getBoundingClientRect()返回0或{top: 0, left: 0, width: 0, height: 0} - 浏览器跳过其布局(Layout)、绘制(Paint)阶段,也不触发该节点的回流(reflow)——但父容器可能因子元素消失而重排
- 不会被屏幕阅读器读取,搜索引擎不索引其内容,
aria-hidden="true"效果等效(但无需显式设置) - 子元素无法绕过继承“显示出来”,因为父节点已从渲染树中移除,子元素自然不可见且无渲染上下文
visibility: hidden —— 节点保留在文档流中,完整参与布局
DOM 节点不仅存在,而且保持全部几何属性和渲染上下文:
- 仍占用原始宽高与位置,
offsetHeight、getBoundingClientRect()返回真实值 - 浏览器照常执行布局与绘制,只是最终像素被标记为“不可见”;切换时仅触发重绘(repaint),不触发回流
- 具有继承性:父元素设
visibility: hidden,子元素默认也隐藏;但子元素可主动设visibility: visible恢复可见 - 屏幕阅读器默认仍会读取其内容(除非额外加
aria-hidden="true"),键盘焦点仍可到达(若元素本身可聚焦)
DOM 节点是否“被移除”?两者都不移除
注意:display: none 和 visibility: hidden 都不会删除或断开 DOM 节点。节点仍存在于 DOM 树中,可被 JS 查询、修改样式、监听事件(visibility: hidden 下事件不可触发,display: none 下事件监听器仍存在但无法冒泡到该节点)。
立即学习“Java免费学习笔记(深入)”;
真正移除节点的是 element.remove() 或 parentNode.removeChild() —— 这和 Angular 的 ng-if 行为一致,而非上述两个 CSS 属性。
实际影响 DOM 操作的关键细节
以下行为在两种隐藏方式下表现不同:
-
获取尺寸:用
offsetHeight判断是否“已显示”时,display: none返回0,visibility: hidden返回实际值 -
事件响应:两者均无法响应鼠标/触摸事件;但
visibility: hidden的子元素若设为visible,可正常交互 -
动画兼容性:
display不支持 CSS transition,必须配合opacity或 class 切换;visibility可过渡(需搭配opacity才有渐变效果) -
可访问性控制:仅靠
visibility: hidden不足以屏蔽屏幕阅读器,需补充aria-hidden="true";display: none则天然隔离


















