遮罩层不能用display: none切换,因其会触发重排且不可过渡,导致表单提交瞬间来不及渲染即被刷新;正确做法是初始设visibility: hidden+opacity: 0,通过opacity过渡显隐。

遮罩层为什么不能用 display: none 切换
表单提交瞬间,浏览器会默认刷新页面或跳转,如果此时靠 JS 控制 display: none 显示遮罩,往往来不及渲染就被中断。更关键的是,submit 事件触发后若未显式 event.preventDefault(),表单立刻提交,JS 后续逻辑(包括遮罩显示)大概率被丢弃。
实操建议:
- 必须在
form的submit事件监听中调用event.preventDefault() - 遮罩元素需提前存在于 DOM 中,且初始为
visibility: hidden或opacity: 0,避免重排开销 - 不要依赖
setTimeout延迟显示遮罩——哪怕只延 1ms,也增加竞态风险
遮罩层的最小可行 CSS 是什么
全屏遮罩核心是覆盖视口、捕获点击、不干扰表单字段聚焦。下面这段 CSS 足够稳定:
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
pointer-events: auto;
opacity: 0;
transition: opacity 0.15s ease;
}
.overlay.active {
opacity: 1;
}
注意点:
-
width: 100vw比100%更可靠,避免因滚动条宽度导致右侧留白 -
pointer-events: auto确保遮罩能响应点击(比如需要点击关闭时),但多数场景设为none更安全 - 避免用
transform: scale(0)或display: none控制显隐——前者有渲染延迟,后者会触发重排
如何与表单提交生命周期对齐
遮罩必须在表单数据真正发出前就生效,否则用户仍可多次点击提交按钮。正确顺序是:禁用按钮 → 显示遮罩 → 发起请求(或触发表单 submit)。
实操建议:
- 给提交按钮加
disabled属性,同时设置aria-busy="true"提升可访问性 - 如果用原生表单提交(非 AJAX),遮罩要在
form.submit()前激活,且确保该调用不被浏览器拦截(例如没有target="_blank"干扰) - 若用
fetch或axios,遮罩应在try块开头启用,finally块中关闭,防止异常导致遮罩残留
移动端键盘收起后遮罩错位怎么办
iOS Safari 和部分安卓浏览器在软键盘弹出/收起时会重置 viewport 高度,导致 100vh 计算错误,遮罩无法覆盖整个可视区域。
解决方案:
- 监听
resize事件,动态更新遮罩高度:overlay.style.height = window.innerHeight + 'px' - 更稳妥的做法是改用
min-height: 100%;+position: fixed;组合,并确保html, body { height: 100%; } - 避免在遮罩内放任何
input或textarea——这会再次唤起键盘,形成循环问题
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











