遮罩层必须用 position: fixed 且与表单同级挂载到 body 下,设 width: 100vw; height: 100vh; z-index: 9999; background: rgba(0,0,0,0.4),并用 touchstart.preventDefault() 防穿透,显隐逻辑需覆盖所有请求路径。

遮罩层必须用 position: fixed,不能嵌在表单内部
把遮罩 <div id="loading"> 写在 <form> 里面,是典型错误。它会随表单滚动、被 overflow 截断、z-index 在局部上下文中失效——尤其当表单父容器加了 transform 或 opacity: 0.99,遮罩就彻底盖不住按钮了。
正确做法是:遮罩层和表单同级,都挂到 <body> 下,并设:
-
position: fixed(不是absolute) -
top: 0; left: 0; width: 100vw; height: 100vh(用vw/vh避免滚动条宽度干扰) -
z-index: 9999(防 Bootstrap、Ant Design 等框架弹窗穿透) -
background: rgba(0, 0, 0, 0.4)(别用opacity,否则加载动画也变淡)
提交时显隐逻辑必须覆盖所有路径,不只是 success
只在 AJAX 成功回调里隐藏遮罩,失败、超时、网络中断时它就永远卡住——用户点不动、关不掉、以为页面崩了。
关键控制点:
立即学习“前端免费学习笔记(深入)”;
- 原生
fetch:用.finally()触发document.getElementById('loading').style.display = 'none' - jQuery
$.ajax:必须配beforeSend(显示) +complete(隐藏),别只写success - 表单原生提交:监听
submit事件,在event.preventDefault()后立刻显示遮罩,再手动发请求 - 初始状态:遮罩默认
display: none,别靠 JS 第一次才创建——避免 FOUC(闪一下)
移动端点击穿透必须用 touchstart.preventDefault()
iOS Safari 和部分 Android WebView 默认允许 touch 事件穿透遮罩层,哪怕它看着盖住了按钮。这不是 bug,是浏览器行为。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
常见误区:
- 设
pointer-events: none在遮罩上 → 它完全不响应,也挡不住点击(反效果) - 只靠
z-index→ 在某些 stacking context 下仍会穿透
真正有效的补丁:
document.getElementById('loading').addEventListener('touchstart', e => {
e.preventDefault();
});
注意:用 touchstart,不是 click —— iOS 的 300ms 延迟会导致误判或卡顿。
遮罩层高度为 0?八成是没写死宽高或忘了 position
即使 CSS 写了 top: 0; left: 0,如果没配 position: fixed,或者没显式声明 width 和 height,遮罩层 DOM 就是个空盒子,渲染高度为 0 —— 看起来像没生效。
最稳写法:
- 强制撑开:
width: 100%; height: 100%不够,要用width: 100vw; height: 100vh - 避免依赖内容:
background本身不占空间,必须靠尺寸属性撑开 - 别信“父容器有 height 就行”——遮罩层已脱离文档流,父容器 height 对它无效
真正难的不是写几行 CSS,而是让遮罩在表单验证失败重试、多步提交、iframe 子页通信等场景下,依然稳稳盖住、不闪、不漏、不卡。这些边界情况,往往只在上线后用户反馈里才暴露出来。


















