全屏加载指示器不能只靠position: fixed,因其易被高z-index弹窗遮挡、无法穿透iframe/原生控件、滚动时定位错乱;可靠方案是挂载至document.documentelement下,用pointer-events: none控制交互,并以vw/vh替代%确保ios safari兼容性。

全屏加载指示器为什么不能只靠 position: fixed?
直接用 div + position: fixed 叠在顶层,看似能盖住页面,但实际会遇到三个硬伤:被 z-index 更高的弹窗挡住、无法穿透 iframe 或原生控件(如 <video></video> 全屏按钮)、滚动时遮罩层位置错乱。真正可靠的方案是把加载指示器挂到 document.documentElement 下,并用 pointer-events: none 避免阻断底层交互——除非你明确需要拦截点击。
如何用自定义元素封装全屏加载逻辑?
用 customElements.define() 注册一个 <full-screen-loader></full-screen-loader>,内部自动处理挂载、尺寸同步和销毁。关键点在于:它必须监听 window.resize 和 scroll(仅当需要跟随滚动时),但更推荐用 position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; ——vw/vh 比 % 更可靠,尤其在 iOS Safari 中避免因地址栏缩放导致的空白。
- 构造函数里调用
this.attachShadow({ mode: 'open' }),避免样式污染 - 使用
getBoundingClientRect()获取视口尺寸不靠谱,改用window.innerWidth和window.innerHeight - 暴露
show()/hide()方法,而非依赖attributeChangedCallback,因为加载状态变化频繁,属性监听有延迟
display: none 会导致 DOM 重排,怎么避免?
每次 hide() 都设 display: none,再 show() 时触发回流。正确做法是用 visibility: hidden + opacity: 0 控制显隐,配合 transition: opacity 0.2s 实现淡入淡出。同时确保初始样式中设置 pointer-events: none,否则隐藏期间仍可能拦截鼠标事件。
- 不要在
hide()中调用this.remove(),否则再次show()得重新创建实例 - 如果页面存在多个实例,用
document.querySelector('full-screen-loader')做单例控制,避免重复渲染 - 动画结束前禁止再次
show(),可用isAnimating标志位防抖
移动端全屏加载要特别注意什么?
iOS Safari 的 vh 在地址栏收起/展开时会跳变,导致遮罩高度忽大忽小。解决方案是监听 visualViewport 事件(Chrome/Safari 支持),或降级为 height: 100% + min-height: 100vh。另外,iOS 上 fixed 元素在 input 获焦后可能错位,必须加 transform: translateZ(0) 强制硬件加速。
- 禁用
-webkit-overflow-scrolling: touch的父容器会影响 fixed 定位,检查外层是否设置了该属性 - 避免在
shadowRoot内使用font-size: 1rem,应统一用px或em,防止根字体大小变化影响尺寸 - 加载图标用
svg而非gif,减少主线程解码开销
真正麻烦的不是实现,而是不同浏览器对 fixed + transform + iframe 的组合处理差异。上线前务必在 iOS Safari、Android Chrome、Edge 最新版上逐个验证遮罩是否始终覆盖整个可视区域。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











