iOS 15 Safari地址栏引发自定义模态框滚动时自动关闭问题求助
我之前在处理iOS 15 Safari的兼容性问题时刚好碰到过一模一样的情况,这个问题的核心是Safari地址栏显示/隐藏时会动态改变视口高度,同时触发页面的隐性滚动,进而干扰了模态框的显示逻辑。下面是几个我验证过有效的解决方案:
方案1:锁定页面滚动并还原滚动位置
当模态框打开时,给页面body添加固定定位,同时记录当前滚动位置,避免地址栏变化触发页面滚动,进而误触模态框关闭逻辑:
/* 模态框激活时给body添加的类 */ .modal-active { position: fixed; width: 100%; height: 100vh; overflow: hidden; top: 0; left: 0; }
let savedScrollPosition = 0; // 打开模态框的函数 function openCustomModal() { // 记录当前滚动位置 savedScrollPosition = window.pageYOffset || document.documentElement.scrollTop; // 添加锁定类 document.body.classList.add('modal-active'); // 修正body偏移,避免页面跳顶 document.body.style.top = `-${savedScrollPosition}px`; // 显示模态框的逻辑(比如设置display: block) document.querySelector('.your-modal').style.display = 'block'; } // 关闭模态框的函数 function closeCustomModal() { // 移除锁定类 document.body.classList.remove('modal-active'); // 恢复之前的滚动位置 window.scrollTo(0, savedScrollPosition); // 隐藏模态框的逻辑 document.querySelector('.your-modal').style.display = 'none'; }
方案2:阻止模态框内的滚动穿透
很多时候模态框自动关闭是因为滚动事件穿透到了页面,触发了绑定在document上的滚动关闭逻辑。我们可以在模态框的滚动容器上监听触摸滚动,阻止边界处的默认滚动行为:
const modalScrollContainer = document.querySelector('.modal-scroll-content'); modalScrollContainer.addEventListener('touchmove', function(e) { const isScrolledToTop = this.scrollTop === 0; const isScrolledToBottom = this.scrollHeight - this.scrollTop === this.clientHeight; // 当滚动到顶部继续上滑,或者到底部继续下滑时,阻止默认滚动(避免触发页面滚动) if ((e.touches[0].clientY > e.changedTouches[0].clientY && isScrolledToTop) || (e.touches[0].clientY < e.changedTouches[0].clientY && isScrolledToBottom)) { e.preventDefault(); } }, { passive: false });
方案3:监听视口高度变化,强制保持模态框状态
iOS Safari地址栏切换时会触发resize事件,我们可以监听这个事件,当检测到视口高度发生较大变化(地址栏切换的特征)时,强制保持模态框的显示状态:
let lastViewportHeight = window.innerHeight; window.addEventListener('resize', function() { const currentModal = document.querySelector('.your-modal[aria-hidden="false"]'); if (!currentModal) return; const heightChange = Math.abs(window.innerHeight - lastViewportHeight); // 地址栏高度变化大概在100px左右,以此作为判断依据 if (heightChange > 50) { // 强制设置模态框为显示状态,覆盖可能触发的关闭逻辑 currentModal.style.display = 'block'; // 同步调整模态框高度为当前视口高度 currentModal.style.height = `${window.innerHeight}px`; } lastViewportHeight = window.innerHeight; });
这些方案的核心思路都是避免地址栏变化带来的页面滚动或视口变化干扰模态框的正常逻辑,你可以根据自己的模态框实现方式选择其中一个或组合使用。
内容的提问来源于stack exchange,提问作者general666
相关产品推荐
相关产品推荐

