网页不像原生应用,很多时候不是功能差异,而是交互细节里的默认网页行为太明显。
1.使用抽屉,而不是全屏页面
移动端更自然的方式是从底部拉起一个抽屉,让用户完成操作后回到原来的上下文。
2.禁止文字被选中
原生应用里的 UI 几乎不会出现蓝色选区,而网页默认允许拖动选中文字,滑动时很容易误触选中。
user-select: none;3.禁用缩放手势
双指缩放和双击放大会打破应用的固定布局,也会让界面立刻回到网页的感觉。
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>4.不需要 cursor: pointer
手指指针更像桌面网页的交互提示,原生应用通常不需要保留它。输入框里的文本指针除外。
5.确保输入框可见
问题在于 iOS PWA 第一次聚焦输入框时,键盘已经弹出,界面却不一定会跟着上移,输入框容易被挡住。
解决方式是监听 visualViewport,用真实可视区域算出输入框被遮住的距离,只滚动缺口那一段,退出输入时交给浏览器恢复。
// 给输入框和键盘之间留出一点呼吸空间。
const margin = 16
function keepInputVisible() {
const viewport = window.visualViewport
const input = document.activeElement
// visualViewport 不存在,或当前焦点不是可定位元素时,不主动处理。
if (!viewport || !(input instanceof HTMLElement)) {
return
}
const rect = input.getBoundingClientRect()
// 把输入框位置和可视区域统一换算到页面坐标,避免键盘改变视口后算错。
const inputTop = rect.top + window.scrollY
const inputBottom = rect.bottom + window.scrollY
const visibleTop = viewport.pageTop + margin
const visibleBottom = viewport.pageTop + viewport.height - margin
// 只补被遮住的距离,不接管浏览器完整的滚动恢复逻辑。
if (inputBottom > visibleBottom) {
window.scrollBy(0, inputBottom - visibleBottom)
} else if (inputTop < visibleTop) {
window.scrollBy(0, inputTop - visibleTop)
}
}
window.visualViewport?.addEventListener('resize', keepInputVisible)
window.visualViewport?.addEventListener('scroll', keepInputVisible)最后,感谢你能看到这里。上面这些都是我在把网页项目转成 App 时遇到的细节问题,它们不复杂,却很容易影响使用感。
更重要的部分,还是 UI/UX 本身:信息是否清楚,操作是否顺手,反馈是否可靠。