display: none 彻底移除元素,不占空间、不触发事件、不被读屏器识别;visibility: hidden 仅视觉隐藏但保留布局、可测尺寸、子元素可单独显示。

display: none 会彻底移除元素,不占空间、不触发事件、不被读屏器识别
设置 display: none 后,元素从渲染树中被完全剔除:它没有尺寸、不参与布局计算、后续兄弟元素立刻上移填补空位。JavaScript 中调用 getBoundingClientRect() 或读取 offsetHeight 都返回 0。display: none 的元素无法获得焦点、不响应任何鼠标/键盘事件,屏幕阅读器默认跳过它——这对表单步骤切换、权限控制类隐藏很合适。
常见误用:
- 在需要保留布局结构的 hover 动画容器上用了
display: none,导致鼠标移入前内容“突然上跳” - 隐藏含
的表单区域却用display: none,结果该字段提交时被浏览器直接忽略(表单序列化时跳过) - 用
element.style.display = ""恢复显示,但空字符串可能继承父级或 UA 默认值(比如inline),而非你预期的block
visibility: hidden 只视觉隐藏,仍占位、可测尺寸、子元素能“穿透”显示
visibility: hidden 不影响文档流:元素盒模型照常存在,margin/padding/height 全部生效,周围元素不动。JS 仍能准确读取它的几何信息,getBoundingClientRect() 返回真实值。它还支持继承——父设 visibility: hidden,子默认也隐藏;但子显式设 visibility: visible 就能单独显示(display 没这能力)。
关键风险点:
- 按钮或链接设了
visibility: hidden,用户仍可用 Tab 键聚焦并回车触发,造成逻辑漏洞 - 表格中对
用 visibility: hidden,部分浏览器下高度异常塌缩- 没配
pointer-events: none,鼠标悬停/点击仍会捕获事件(只是用户看不到反馈)动画与性能:visibility 可过渡,display 不行
display是非连续 CSS 属性,不能参与transition或@keyframes。想实现淡出效果,硬切display: none会导致生硬跳变。而visibility可以和opacity配合做平滑过渡:/* 正确组合 */ .hidden { visibility: hidden; opacity: 0; transition: opacity 0.2s; } .showing { visibility: visible; opacity: 1; }这样既避免 layout thrashing(
visibility切换只触发重绘),又保证动画结束时元素不可交互(visibility: hidden阻断焦点和事件)。注意:别用opacity: 0单独替代二者——它仍响应事件、参与 z-index 层叠、影响可访问性。媒体查询与选择器权重冲突时,display 优先级更高
当一个元素同时被多个规则设置
display和visibility,display: none会直接让visibility失效——因为元素已不在渲染树里。例如:@media (max-width: 768px) { .nav { visibility: hidden; } } .layout .nav { display: block; } /* 这条权重更高,覆盖 media 查询,但 nav 仍可见 */如果反过来:
.layout .nav { display: none; } @media (max-width: 768px) { .nav { visibility: visible; } /* 无效:display: none 已让元素消失 */ }所以别指望靠
visibility“救活”被display: none干掉的元素。真正要响应式切换,统一用一种机制,或用 JS 控制 class 切换更可控。实际调试时最省事的判断方式:打开 DevTools → Elements 面板选中目标元素 → 看右侧 Computed 栏里
display和visibility的最终值;再切到 Layout 面板勾选 “Show layout shifts”,看隐藏前后是否引发周围元素位置变动——动了,就是display在起作用;没动,基本是visibility或opacity。 - 没配
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











