display: none
和 visibility: hidden
都是用于控制元素可见性的 CSS 属性,但它们的行为和影响有显著区别。以下是两者的详细对比(嫌文章太长直接看总结即可):
一、是否占据页面空间
属性 | 是否占据空间 |
display: none | 不占据空间,元素完全从布局中移除。 |
visibility: hidden | 仍占据空间,只是不可见。 |
示例效果:
display: none
:元素消失后,后续内容会填补其位置(布局重新计算)。visibility: hidden
:元素不可见,但原来的空间保留(布局不变)。
二、是否渲染元素
属性 | 是否渲染元素 |
display: none | 元素不被渲染,不在文档流中。 |
visibility: hidden | 元素仍被渲染,只是不可见。 |
影响:
display: none
的元素不会触发任何事件(如点击、悬停),因为元素不在渲染树中。visibility: hidden
的元素仍可响应 JavaScript 操作(如点击事件)。
三、是否影响布局
属性 | 是否影响布局 |
display: none | 会改变页面布局(触发重排)。 |
visibility: hidden | 不影响布局(仅触发重绘)。 |
性能差异:
display: none
会触发 重排(reflow),性能开销较大。visibility: hidden
仅触发 重绘(repaint),性能更优。
四、子元素的继承行为
属性 | 子元素是否继承 |
display: none | 子元素也不显示,无法通过 CSS 恢复。 |
visibility: hidden | 子元素可通过 visibility: visible 显示。 |
影响:
display: none
的元素不会触发任何事件(如点击、悬停),因为元素不在渲染树中。visibility: hidden
的元素仍可响应 JavaScript 操作(如点击事件)。
示例代码:
<!-- display: none -->
<div style="display: none;">
<p>子元素也无法显示</p>
</div>
<!-- visibility: hidden -->
<div style="visibility: hidden;">
<p style="visibility: visible;">子元素可见</p>
</div>
五、无障碍访问(ARIA)
属性 | 是否可被访问 |
display: none | 无法通过屏幕阅读器读取。 |
visibility: hidden | 可被屏幕阅读器读取(不推荐用于隐藏内容)。 |
注意:
- 如果需要隐藏内容但仍需支持无障碍访问,建议使用
aria-hidden="true"
或将元素移出文档流(如position: absolute; left: -9999px
)。
六、 应用场景
场景 | 推荐属性 |
完全隐藏元素(不占空间) | display: none |
隐藏元素但保留布局(如占位符) | visibility: hidden |
动态切换显示状态(性能优先) | visibility: hidden |
彻底移除元素(如 tab 切换未激活项) | display: none |
注意:
- 如果需要隐藏内容但仍需支持无障碍访问,建议使用
aria-hidden="true"
或将元素移出文档流(如position: absolute; left: -9999px
)。
注意事项
- 如果需要频繁切换显示状态,优先使用
visibility: hidden
(性能更优)。 display: none
会移除元素,适合一次性隐藏(如 tab 切换中未激活的项)。- 如果需要隐藏元素但仍需保留其交互能力(如悬停效果),使用
visibility: hidden
。 - 避免使用
visibility: hidden
隐藏敏感内容(如密码字段),因其仍可被开发者工具查看。
总结
display: none
:
元素完全从文档流中移除,不占据任何空间。
页面会重新布局(触发重排),后续元素会上移填补位置。
子元素也会被隐藏,且无法单独显示。
不渲染,不响应事件,也不会被屏幕阅读器读取。
适用于彻底隐藏元素,比如弹窗关闭、标签页切换等。
visibility: hidden
:
元素仍然占据原来的空间,布局不变。
不触发重排,只触发重绘,性能更好。
子元素可以通过设置
visibility: visible
单独显示。元素仍存在于渲染树中,可响应 JavaScript 事件。
适用于需要保留占位但暂时不可见的场景,比如 loading 占位、动画过渡等。