display: none触发重排,visibility: hidden仅触发重绘;前者彻底移除渲染树,后者保留布局占位且子元素可覆盖显示,二者在焦点、动画、表单提交等行为上存在关键差异。

display: none 会触发重排,visibility: hidden 只重绘
浏览器渲染流程分三步:样式计算 → 布局(Layout/Reflow)→ 绘制(Paint/Repaint)。display: none在布局阶段就被跳过,父容器尺寸重算、兄弟元素位置重排,必然触发重排;而visibility: hidden仍参与布局,只是绘制阶段被跳过,只触发重绘。
常见踩坑点:
- 轮播图切换时对非当前项用
display: none→ 容器高度反复塌缩/撑开,造成视觉抖动 - 表单校验提示用
display: none收起 → 下方按钮上移,用户点击错位 - Canvas 容器内子元素设
display: none→canvas.getContext('2d')可能因尺寸突变返回空画布
visibility: hidden 的元素仍可被 focus(),但 display: none 不行
visibility: hidden下的<input>或<button></button>仍能被 JS 调用focus(),但光标不可见、键盘操作无效;display: none则直接无法获得焦点,调用focus()无反应,也不会触发focusin事件。
实操建议:
- 若需保留焦点逻辑(比如模态框关闭后自动聚焦到触发按钮),别用
display: none隐藏模态内容 - 用
getComputedStyle(el).visibility === 'hidden'判断是否“视觉隐藏”,而非仅靠offsetHeight === 0(两者都返回0) - 禁用表单提交字段时,
display: none不阻止name值提交,得配合disabled或删name属性
子元素能否穿透显示,是关键行为分水岭
visibility: hidden可被子元素用visibility: visible覆盖,实现“父遮罩、子透出”;display: none下所有后代节点彻底退出渲染树,任何 CSS 都无法恢复。
典型误用场景:
- 模态框遮罩层设
visibility: hidden,但内部弹窗忘了加visibility: visible→ 整个弹窗消失 - 悬停菜单对子项用
display: none控制显隐 → 鼠标移入时元素已不在渲染树中,:hover失效 - 想做“仅屏幕阅读器可见”的 skip-link,用
visibility: hidden+position: absolute比display: none更安全
transition 动画根本不能作用于 display 属性
transition: display 0.3s完全无效——display是离散值(block/none/inline等),没有中间状态;visibility虽可过渡,但浏览器通常直接跳帧,需搭配opacity才真正平滑。
可靠做法:
- 先设
opacity: 0; visibility: hidden;,再加transition: opacity 0.3s - 动画结束回调里再设
display: none(避免占位) - 反向显示时,先
display: block→ 强制重排 → 再opacity: 0; visibility: hidden;→opacity: 1
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











