最轻量可控的遮罩层方案是用#loading配合display:none切换,必须设position:fixed、z-index≥9999、background:rgba(0,0,0,0.4),禁用transition;需在window.onload而非DOMContentLoaded后隐藏;AJAX中用beforeSend/complete(或fetch.finally)控制显隐;移动端需防touch穿透,可加touchstart.preventDefault();动画优先用GIF或低开销CSS。

直接加一个 #loading 遮罩层,配合 display: none 切换,是最轻量、最可控、兼容性最好的做法——别用 opacity 控制整个页面透明度,那会把按钮文字也变淡,用户根本看不清。
遮罩层必须用 position: fixed,不是 absolute
用 absolute 时,遮罩层会随滚动条消失;用 fixed 才能始终盖住视口。常见错误是写成 top: 0; left: 0; width: 100%; height: 100% 却忘了加 position: fixed,结果只遮了首屏内容。
-
z-index至少设为9999(避免被第三方 CSS 覆盖) - 背景推荐用
background: rgba(0, 0, 0, 0.4),比filter: alpha(opacity=40)更现代、更可靠 - 不要给遮罩层加
transition动画,首次显示时容易闪一下或延迟
DOMContentLoaded 不等于资源加载完成
只监听 DOMContentLoaded 就隐藏遮罩,可能图片、字体、子 iframe 还没加载完,用户看到的是“半成品页面”。真正要等的是所有资源就绪,得用 window.onload。
-
DOMContentLoaded:DOM 树构建完就触发(HTML 解析完) -
window.onload:所有资源(img、link、iframe等)都下载渲染完才触发 - 如果页面有大量图片,建议在
window.onload后再loading.style.display = 'none'
AJAX 请求中控制遮罩显隐,必须用 beforeSend 和 complete
jQuery 的 $.ajaxSetup 是最省事的方式,但要注意:不能只在 success 里隐藏遮罩——失败、超时、网络中断时遮罩也会卡住不退。
立即学习“前端免费学习笔记(深入)”;
-
beforeSend:发起请求前显示遮罩(可顺便禁用提交按钮) -
complete:无论成功失败,请求结束就隐藏遮罩(这才是关键) - 原生
fetch没有内置钩子,需手动在finally块里调用隐藏逻辑
移动端要防 touch 事件穿透
遮罩层显示时,用户仍可能点到下层按钮,尤其在 iOS Safari 上。这不是 bug,是浏览器默认行为。
- 给遮罩层加
pointer-events: none?错,这会让它完全不可交互,也无法挡住点击 - 正确做法是加
pointer-events: auto(默认值),并确保它z-index足够高 - 更稳妥的补丁:在遮罩层上监听
touchstart并event.preventDefault(),阻止事件冒泡到底层
最易忽略的一点:遮罩层里的加载动画(比如 .spinner)如果用了 transform: rotate(),在旧版 Android WebView 中可能卡顿或不转——优先用 GIF,或至少 fallback 到 animation: spin 1s steps(12) 这类低开销写法。



















