iOS Safari底部冗余空白颜色Bug技术问询
调试其他iOS问题时,发现一个十分怪异的iOS Safari Bug:
复现步骤
- 在iOS Safari中打开演示页面
- 点击输入框唤起虚拟键盘
- 将页面滚动至最底部
- 观察页面底部的空白块
已在iOS 16.4.1(iPhone 13)上复现该问题。
问题解答
页面底部为何会出现冗余空白?
这是iOS Safari在虚拟键盘唤起时的视图计算Bug。当键盘弹出后,Safari会调整视窗高度,但滚动到最底部时,页面实际可滚动区域的计算没有跟上视窗的动态变化,导致原本被键盘覆盖的区域在视觉上出现空白——本质是Safari没有正确更新页面的滚动边界,把键盘占用的空间错误地保留为可滚动区域的一部分。为何该冗余空白块仅在iOS Safari中显示为白色,其他浏览器(甚至iOS Chrome)均无此现象?
iOS Chrome等第三方浏览器基于WebKit内核,但苹果给Safari保留了专属的视窗管理逻辑,第三方浏览器受限于App Store的沙盒机制,无法完全复用Safari的原生视窗调整策略。Safari的这个空白是其原生渲染层的默认背景色(白色),而第三方浏览器的视窗处理逻辑更贴合标准Web规范,不会出现这种原生层暴露的问题。底部白色空白块的高度由什么决定?
空白块的高度等于虚拟键盘的高度。当键盘唤起时,Safari错误地将页面的可滚动高度计算为「原视窗高度 - 键盘高度」的反向值,导致滚动到底部时,多出的区域正好是键盘占据的垂直空间。为何将style.css第8行替换为
body {background-color: yellow}时,空白块变为透明,但替换为body {background-color: #fefefe}时仍为白色?
这是因为Safari原生渲染层的默认背景色就是白色(#ffffff)。当body设置为#fefefe时,颜色和原生层几乎一致,视觉上看起来空白块还是白色;而设置为yellow时,body颜色和原生层差异明显,此时空白区域暴露的是页面下方的透明层(因为body没有覆盖到该区域),所以看起来是透明的(实际是系统背景,但和body黄色形成对比后显透明)。为何将第17行替换为
min-height: 25px;时,底部空白块变为透明?
原代码中min-height: 100vh会让元素高度等于视窗高度,但键盘唤起后,100vh的计算没有实时更新(iOS Safari的vh在键盘弹出时存在滞后问题)。改为25px后,元素高度远小于视窗,页面的实际滚动高度被限制,Safari的滚动边界计算错误被规避,不会出现超出body范围的滚动区域,也就不会暴露原生白色背景层。
内容的提问来源于stack exchange,提问作者Maksym

