display: none 触发重排,visibility: hidden 仅重绘;前者移出文档流影响布局且不可过渡,后者保留空间、支持配合 opacity 实现淡入淡出,且表单元素隐藏时仍可提交。

display: none 触发重排,频繁切换易导致 layout thrashing
每次设置 display: none 或从它切回(如 display: block),浏览器必须重新计算整个布局树——因为元素进出文档流会改变其他元素的位置、尺寸、换行等。这种强制重排(reflow)开销远高于重绘。
常见错误现象:
- 在
for循环中反复读取offsetHeight后立即设display: none,触发连续重排,页面卡顿 - 用
display控制下拉菜单显隐,鼠标快速进出时出现明显“抖动”或延迟响应 - 动画帧内混合
display切换与尺寸读取,Chrome 会降级为同步布局,拖慢 FPS
visibility: hidden 只触发重绘,适合高频/动态隐藏
visibility: hidden 不改变文档流,元素的 offsetWidth、getBoundingClientRect() 等仍返回真实值,浏览器只需重绘(repaint)该区域像素,不涉及布局重算。
适用场景:
- 轮播图切换图片时,用
visibility: hidden避免容器高度塌缩导致的视觉跳动 - Tooltip 预渲染容器始终存在,仅靠
visibility控制显隐,保证定位锚点稳定 - Canvas 父容器需临时隐藏又恢复——
visibility: hidden不销毁渲染上下文,display: none可能导致空白
transition 动画中二者行为完全不同
display 不是可过渡的 CSS 属性,写 transition: display 0.3s 完全无效;而 visibility 虽不可直接过渡,但配合 opacity 可实现平滑淡出:
button {
visibility: hidden;
opacity: 0;
transition: opacity 0.2s, visibility 0.2s;
}
button.show {
visibility: visible;
opacity: 1;
}
注意:动画结束前不能切回 display: none,否则会中断过渡。
表格行和表单控件有特殊表现
部分浏览器对 <tr> 应用 <code>visibility: hidden 时,<tbody> 高度计算异常(显示为 0),应改用 <code>display: none 或包裹 <div>。
<p>表单提交场景下:<code><input name="email"> 设 display: none 后不会被提交;但 visibility: hidden 下仍会提交——若需隐藏又保留提交,得加 disabled 或移除 name,而非依赖 visibility。
真正容易被忽略的是:两者都默认禁用鼠标事件,但 visibility: hidden 的元素仍参与事件捕获路径(只是看不见),要彻底屏蔽需额外加 pointer-events: none;而 display: none 的元素根本不在事件路径中,无需此操作。
部分浏览器对 <tr> 应用 <code>visibility: hidden 时,<tbody> 高度计算异常(显示为 0),应改用 <code>display: none 或包裹 <div>。
<p>表单提交场景下:<code><input name="email"> 设 display: none 后不会被提交;但 visibility: hidden 下仍会提交——若需隐藏又保留提交,得加 disabled 或移除 name,而非依赖 visibility。
真正容易被忽略的是:两者都默认禁用鼠标事件,但 visibility: hidden 的元素仍参与事件捕获路径(只是看不见),要彻底屏蔽需额外加 pointer-events: none;而 display: none 的元素根本不在事件路径中,无需此操作。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











