移动端常见兼容问题
场景
同样的代码在 iOS 和 Android 上表现不一致,软键盘弹起布局错乱、滚动穿透、日期格式解析失败等。如何系统性地处理移动端兼容问题?
常见问题与解决方案
1. 软键盘弹起导致布局问题
keyboard-handler.ts
// iOS:键盘弹起时 viewport 被压缩(webview resize)
// Android:键盘弹起时 viewport 不变(键盘覆盖在页面上)
// 方案:监听 resize + visualViewport API
if (window.visualViewport) {
window.visualViewport.addEventListener('resize', () => {
const keyboardHeight =
window.innerHeight - window.visualViewport!.height;
if (keyboardHeight > 150) {
// 键盘弹起 → 调整底部固定元素位置
document.documentElement.style.setProperty(
'--keyboard-height',
`${keyboardHeight}px`
);
} else {
document.documentElement.style.setProperty('--keyboard-height', '0px');
}
});
}
底部固定元素适配
.bottom-bar {
position: fixed;
bottom: calc(0px + var(--keyboard-height, 0px));
}
2. 滚动穿透
弹窗打开时,背景页面仍然可以滚动。
prevent-scroll.ts
function preventScroll(enable: boolean) {
if (enable) {
// 记录当前滚动位置
const scrollY = window.scrollY;
document.body.style.position = 'fixed';
document.body.style.top = `-${scrollY}px`;
document.body.style.width = '100%';
document.body.dataset.scrollY = String(scrollY);
} else {
const scrollY = Number(document.body.dataset.scrollY ?? 0);
document.body.style.position = '';
document.body.style.top = '';
document.body.style.width = '';
window.scrollTo(0, scrollY);
}
}
3. 日期解析兼容
date-compat.ts
// ❌ iOS Safari 不支持 "2024-01-15 10:30:00" 格式
new Date('2024-01-15 10:30:00'); // iOS 返回 Invalid Date
// ✅ 替换为 ISO 格式或手动替换
new Date('2024-01-15T10:30:00');
new Date('2024-01-15 10:30:00'.replace(/-/g, '/'));
// 或 replace(' ', 'T')
4. 1px 边框
1px 方案
/* 利用 transform 缩放 */
.border-1px {
position: relative;
}
.border-1px::after {
content: '';
position: absolute;
inset: 0;
border: 1px solid #e5e5e5;
border-radius: inherit;
transform: scale(0.5);
transform-origin: 0 0;
pointer-events: none;
width: 200%;
height: 200%;
}
5. 安全区域适配
safe-area.css
/* iPhone X+ 刘海屏 / 底部横条适配 */
.page {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
/* 底部固定栏 */
.bottom-bar {
padding-bottom: calc(12px + env(safe-area-inset-bottom));
}
问题速查表
| 问题 | iOS 表现 | Android 表现 | 解决方案 |
|---|---|---|---|
| 软键盘 | resize viewport | 覆盖页面 | visualViewport API |
| 滚动穿透 | 常见 | 较少 | body fixed + 滚动恢复 |
| 300ms 延迟 | 已修复 | 已修复 | touch-action: manipulation |
| 日期解析 | 格式严格 | 格式宽松 | ISO 格式/手动替换 |
| 橡皮筋效果 | 有 | 无 | overscroll-behavior: none |
| 输入框 zoom | Safari 自动放大 | 无 | font-size: 16px |
常见面试问题
Q1: iOS Safari 有哪些常见的坑?
答案:
- 日期格式解析严格(不支持
YYYY-MM-DD HH:mm:ss) position: fixed在键盘弹起时失效- 橡皮筋效果(overscroll bounce)
- 输入框 font-size < 16px 时自动缩放
- 100vh 包含地址栏高度(用
dvh或 JS 计算) <audio>autoplay 被限制
Q2: 如何处理移动端 click 事件的 300ms 延迟?
答案:
现代浏览器已基本解决(设置 <meta name="viewport"> 后)。如果仍有问题:
- CSS:
touch-action: manipulation - 使用
touchend代替 click - 使用 FastClick 库(已不推荐)