跳到主要内容

移动端常见兼容问题

场景

同样的代码在 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
输入框 zoomSafari 自动放大font-size: 16px

常见面试问题

Q1: iOS Safari 有哪些常见的坑?

答案

  1. 日期格式解析严格(不支持 YYYY-MM-DD HH:mm:ss
  2. position: fixed 在键盘弹起时失效
  3. 橡皮筋效果(overscroll bounce)
  4. 输入框 font-size < 16px 时自动缩放
  5. 100vh 包含地址栏高度(用 dvh 或 JS 计算)
  6. <audio> autoplay 被限制

Q2: 如何处理移动端 click 事件的 300ms 延迟?

答案

现代浏览器已基本解决(设置 <meta name="viewport"> 后)。如果仍有问题:

  • CSS:touch-action: manipulation
  • 使用 touchend 代替 click
  • 使用 FastClick 库(已不推荐)

相关链接