记一次 iOS Safari 的诡异 Bug

这个 Bug 折磨了我两天,记录一下,希望能帮到遇到类似问题的人。

现象

有个全屏弹窗,在 iOS Safari 上打开后,滚动到底部,再往上滑,页面内容会”弹”一下,然后底部留白。

更诡异的是,这个 Bug 只在生产环境出现,本地开发环境完全没问题。

排查过程

第一天:怀疑样式

首先想到的是 position: fixed100vh 的问题。iOS Safari 的地址栏会收起和展开,导致 100vh 计算不准确。

试了网上常见的方案:

.modal {
  height: 100vh;
  height: -webkit-fill-available;
}

没用。

又试了用 JS 计算:

const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);

还是不行。

第二天:怀疑渲染

开始怀疑是不是 React 的渲染问题。加了 key 强制重渲染,没用。

然后我在本地模拟生产环境打包,发现问题复现了。原来是生产环境的压缩或者某些配置导致的。

进一步排查,发现是 overscroll-behavior 的锅。我们在全局样式里写了:

html {
  overscroll-behavior: none;
}

iOS Safari 对这个属性的处理有问题,导致滚动行为异常。

解决方案

.modal {
  position: fixed;
  inset: 0;
  overflow: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.modal-content {
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
}

关键点是把 overscroll-behavior: contain 加到弹窗内容上,而不是全局。

教训

  1. iOS Safari 的怪 Bug 很多,遇到问题先查兼容性
  2. 生产环境和开发环境的差异要重视
  3. 有些 CSS 属性看着有用,实际可能引入新问题

另外推荐个网站:can I use,查兼容性必备。还有 WebKit Bugzilla,遇到怪问题可以去搜搜看是不是已知 Bug。

最后吐槽一句:移动端 Web 开发太痛苦了,每个浏览器都有自己的脾气。