iOS 兼容到底有多难

同一个「输入面板贴着键盘弹起来」的效果,安卓上一行配置,iOS 上折腾了一整天。说说 iOS Safari 在键盘、聚焦、滚动上的几个特性,以及为什么它们凑在一起就格外难缠。

备注

本站手机评论区做了一个 B 站式的输入面板:点一下评论栏,面板从底部弹起、贴着键盘。安卓上一行配置就搞定了,iOS 上前后改了三版、十几个提交,最后还留了一处没修。这篇不讲过程,只讲 iOS 到底哪里特殊。

安卓:一行配置

安卓 Chrome 允许网页选择「键盘弹出时把页面挤矮」。在 viewport 里加一句 interactive-widget=resizes-content,键盘一出来,页面就缩到键盘上方,面板写个 bottom: 0 自然贴住键盘,不需要任何 JS。

iOS 没有这个开关。

iOS 的几个特性

特性表现对开发的影响
键盘只盖住页面,不挤小页面页面布局纹丝不动,键盘直接压在上面CSS 的 fixed、sticky、视口单位都以「没被挡住的完整页面」为准,CSS 永远不知道键盘在哪,只能用 JS 读 visualViewport 去算
聚焦输入框会自动滚动每点一个框,iOS 都要把它挪到可视区域中间,哪怕它本来就看得见页面上任何「贴着某处」的东西都会被带着晃,而且手指点、键盘上的上下箭头、程序里调 focus() 都会触发,拦不全
字号小于 16px 的输入框一聚焦就放大整页被放大,还能被拖着走要么所有输入框字号 ≥ 16px,要么想办法关掉;常见的 maximum-scale=1 在 iOS 版 Chrome 上会把双指缩放也禁掉
键盘弹出时可视区域能被拖动页面明明锁了滚动,手指一划照样动overflow: hidden 拦不住,得用 JS 拦触摸,或者把整页钉死
底部工具栏下面不画固定元素(iOS 26)固定在屏幕上的背景到工具栏上沿就断了网页这边基本绕不过去,只能让露出来的那截颜色别太突兀
只有真机上才会出现电脑浏览器、手机模拟器里一切正常每改一次都得在 iPhone 上测一轮,排查只能靠在页面上打日志、截图

这些特性单独拿出来都还好办,难在它们会叠在一起:为了让面板贴住键盘,得用 JS 追着键盘位置走;可每次聚焦输入框,iOS 都会先把页面挪一下,JS 要等它挪完才追得上,面板就「被带走、再被拨回」,看着就是抖一下。去拦聚焦,又发现入口不止一个;去锁滚动,又发现 overflow: hidden 锁不住。

我们最后怎么收场的

拦不全,就别跟它对着干。iOS 上面板不再贴键盘,改成贴屏幕顶部往下展开,不用 JS 追;面板开着时把整个页面钉死,让 iOS 没得滚。其余平台照旧贴键盘。

判断「是不是 iOS」用的是一个只有 iOS 浏览器认识的 CSS 属性 -webkit-touch-callout,CSS 和 JS 两边都按它分开处理,不去解析浏览器的标识字符串。

最后留了一处没修:没登录时面板里有四个框,正文框在最下面,切到它时 iOS 还是会把面板挪一小段(约 22px)。能修,但又得再上真机测一轮,换来的只是没登录时少动一下,就停在这儿了。

为什么没人修

不是没人提。WebKit 有个「键盘弹出时视口机制失灵」的 bug 从 2018 年开到现在;谷歌的工程师也去 WebKit 那边提议过「让网页可以选择被键盘挤小」,至今挂着「需要表态」,苹果没回应。Chrome 和 Firefox 都在往前走,Safari 一直没跟进。

所以在可见的将来,iOS 上想让东西贴住键盘,还是只能写 JS,还得和它的自动滚动周旋。

参考

资料说的是什么
WebKit Bug 191204键盘弹出时视口机制失灵,2018 年至今未修
WebKit Bug 259770Safari 未实现 interactive-widget
WebKit standards-positions #65「让网页选择被键盘挤小」的提议,苹果未表态
MDN:Visual Viewport API键盘缩小的是可视视口,不是布局视口
Rick Strahl:Preventing iOS Textbox Auto Zooming16px 与 maximum-scale 的取舍

评论

评论加载中……

登录后再评论

注册要用邮箱收个验证码,只为确认邮箱能收信,不会拿去做别的。账号设置