Safari又出bug了?临时修复 iOS 26弹出键盘后定位错乱问题

1,353 阅读4分钟

欢迎关注我的公众号:前端侦探

Safari真不愧是新时代的IE。由于 iOS 26最近发布,一下子把我的页面搞乱了

一、定位错乱问题

比如这样一个上下fixed定位布局

<header>头部</header>
<div class="list">
  <div class="item"></div>
  <input placeholder="请输入">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>
<footer>底部</footer>

相关样式如下

header{
  position: fixed;
  top: 0;
  left:0;
  right:0;
  background: pink;
  padding: 10px;
  padding-top:padding-bottom: calc(env(safe-area-inset-top) + 10px);
}
footer{
  position: fixed;
  bottom: 0;
  left:0;
  right:0;
  background: orange;
  padding: 10px;
  color: #fff;
  padding-bottom: calc(env(safe-area-inset-bottom) + 10px)
}

正常情况下没什么问题,上下的吸顶(底)的

image-20250921130022828

但是当呼出键盘后,再次滚动页面,上下定位就出现了偏差

image-20250921130227372

很明显,上下本该贴近屏幕边缘的fixed元素居然错乱了,看着像是整体向上偏移了,导致顶部移出屏幕了,底部漏出一个缝隙。

如果大家手头有iOS 26设备,可以访问这个demo自己体验一下

xboxyan.codelabo.cn/source/ios2…

或者直接扫码体验

image-20250921130751857

为了验证这个不是特例,特意去看了苹果官网,只要有输入框的,触发以后也会出现这种现象(顶部的导航栏往上偏移了)

image-20250921131043993

目前在苹果开发者平台已经看到有相关反馈了,看看什么时候可以修复吧。

developer.apple.com/forums/thre…

那么,在苹果修复之前,有什么办法可以规避这个问题呢?

二、使用容器滚动来代替页面滚动

其实在之前就有这种感觉,safari的页面滚动很容易受到系统行为的影响,给人一种不可靠的感觉,每次系统更新都得看下当前页面是否受影响。

这次的问题也是这样,不知道苹果的底层对webview做了什么特殊优化,导致键盘弹起后整体页面布局出现了偏差。所以这里的解决方式就是使用容器滚动而不是默认的页面滚动。

拿上面的例子来说,最简单的方式是直接嵌套一层

<div class="page"> 
  
</div>

然后设置容器滚动

html,body,.page {
  margin: 0;
  height: 100%;
}
.page {
  overflow: auto;
  overscroll-behavior: none; /*阻止默认滚动行为*/
}

为了彻底消除系统滚动影响,还可以加上overscroll-behavior: none;,这个属性可以阻止系统的默认滚动行为,比如iOS上的默认回弹效果,滚动联动效果

之前在这篇文章中有详细介绍: 两分钟小技巧!如何阻止 macOS 的触底弹性滚动和双指手势导航

这样这个页面就只有容器滚动了,根本不会触发页面滚动那些乱七八糟的系统行为了。

你可以访问这个demo

xboxyan.codelabo.cn/source/ios2…

或者直接扫码体验

image-20250921133659301

这样问题基本就解决了

三、对现有页面的影响

当然如果是一个已经存在的项目,仅仅以上改动还不够,布局可能没问题了,但是还有一些其他问题。比如有些逻辑是依赖页面滚动的,比如上拉加载,可能之前是通过监听页面滚动实现的,这里要统一改成容器监听

window.addEventListener('scroll', () => {})
// 改为
document.getElementById('#app').addEventListener('scroll', () => {})

然后滚动位置的获取也要改变

document.scrollingElement.scrollTop
//改为
document.getElementById('#app').scrollTop

如果之前在写这些计算逻辑时考虑到了滚动容器,那么这个改动适配就很轻松,否则就有点麻烦了。

四、iframe好像也行?

如果页面要修改的地方太多了,各种滚动计算,或者依赖的第三方库根本就不支持容器滚动,还可以试试iframe容器,结构很简单

<style>
  html,body,iframe{
    margin:0;
    height: 100%;
    width: 100%;
    border:0;
    overflow: hidden;
    overscroll-behavior: none;
  }
</style>
<body>
  <iframe src="./index.html"></iframe>
</body>

这样就是一个最简单的结构了,其实也相当于变相去掉了页面滚动,iframe里的页面滚动系统可不认。

你可以访问这个demo

xboxyan.codelabo.cn/source/ios2…

或者直接扫码体验

image-20250921140816690

当然实际项目中可能还有各种参数,需要一一传递过来,然后还有iframe的性能一直是个问题,加载比较慢,适合一定要解决这个问题又不想大改的场景。

五、希望尽快修复吧

移动端80%的问题都来源于safari,真的是毫无办法,别的不说了,尽快修复吧。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发 ❤❤❤