Web 移动端开发

427 阅读10分钟

本文所说的 Web 移动端开发的网页,仅指在移动端用浏览器打开这些网页,不包括移动端的本地应用或者混合式开发。这篇文章的主要目的,是收集开发 Web 移动端时常见的问题及解决方案,同时对Web 移动端开发有更系统的理解。

1. 移动端和 PC 端的差别

  • 屏幕更小
    • 弹性布局
  • 触摸屏:
    • 支持 touch
    • 无 hover 态
    • 不如鼠标精准
  • 支持旋转
    • Portrait 竖屏
    • Landscape 横屏
  • 支持地理定位
  • 支持重力感应
  • 不用考试兼容低版本 IE
    • 支持的新特性更多

2. Mobile Friendliness

参考:Mobile Friendliness

2.1 目标

  • 呈现:在不同尺寸的屏幕上,网页都能很好地展现出来
  • 内容:专为移动端用户准备的内容
  • 性能:流畅的用户体验,即使网络很慢

Note:了解你的目标用户,知道他们在用哪些设备

2.2 实现方案

2.2.1 为移动端单独设计

目前比较流行为移动端用户创建一个不同于桌面端的新站点,如 m.toutiao.tom 。通过用户代理嗅探, 在服务端就将移动端用户导向移动端页面,有时也通过前端页面来进行重定向。

  • 优点:
    • 只有移动端相关资源才被传送,更高效
    • 简单,不影响已有项目
  • 缺点:
    • 增加维护成本(网站中所有页面都存在两个版本)
    • 用户代理嗅探有内在缺陷
    • 多一套 URL,影响 SEO 效果
  • 适用场景:
    • 目标用户大都是低端机,可能无法识别 HTML
    • 移动端和桌面端的两个版本有很大差异
    • 出于某种原因,不能修改现有代码的情况下新增移动端

2.2.2 响应式

响应式是指一个页面可以很好地适配不同大小的屏幕,通过媒体查询和弹性布局实现。示例

  • 优点:
    • 只需维护一个站点
    • 不依赖代理嗅探
    • SEO 更好
  • 缺点:
    • 性能问题,移动端即使内容更少,也要加载和PC一样的资源,尤其是图片
    • 移动设备的操作习惯在响应式下不能达到最佳
  • 适用场景:
    • 适合桌面端和移动端内容非常相似
    • 页面内容不太复杂

2.3.3 混合式

不管是为移动端单独建站还是做响应式,都有各自的优缺点。我们也可以根据实际情况在不同的方面将二者结合在一起。下面举一些例子:

  • 仅将代理嗅探用于内容的展示,样式用响应式
  • 再比如图片,响应式最为人诟病的就是不管什么设备都用同样分辨率的图片,有时这在一些设备上是无意义的。这种可以通过服务端的用户代理嗅探来解决
  • 即使是为移动端单独建站,也会用到响应式,让内容更好地适应各种屏幕大小,比如平板

混合的方式,代码会多很多分支,提高复杂度,正所谓「没有银弹」。

3. 移动端浏览器

3.1 兼容性

下图是 2012 年到 2019 年的移动端浏览器市场占有率统计。数据来源 总的来说,移动端的浏览器大都基于 webkit,所以支持很多较新的特性。但是不排除一些低版本手机有一些兼容问题,如 Android 5.0.2 及以下仍然不支持小于 12px 的字号、Android Browser 4.3 及以下不支持 Flex 布局等。

技术在发展,具体到实现的时候,还是要收集目标用户设备数据,参考caniuse,最后以实际设备测试为准。也可以借助一些在线工具来测试不同设备。

3.2 调试

  • Chrome 的移动端模拟器,这是最主要的调试方式
  • Chrome 连接 Android 上的 webkit 浏览器真机调试
  • Safari 连接 iPhone 真机调试

4. 屏幕大小适配

许多站点并没有专门针对移动端的小屏幕做设计,为了尽量正常显示这些站点,浏览器会给 viewport 设置一个较宽的值,比如 980px。

4.1 理想适配

理想适配满足以下条件:

  • 没有横向滚动条,用户只需下滑屏幕查看更多内容
  • 不用手动缩放就可以正常查看网站所有内容,比如不会因为文字太小而看不清楚
  • 热点区域大小方便点击

为达到理想适配,使 viewport 的宽度和屏幕宽度相同,通常做如下配置:

<meta name="viewport" content="width=device-width,initial-scale=1"> 

Content 中设置 width 和 initial-scale 是同样的效果,但兼容性有差异,所以经常一起出现。

4.2 平板电脑怎么适配?

平板电脑的观看距离和手机是一样的,但是屏幕大得多,像 iPad pro 屏幕大小接近笔记本电脑。在这些设备上用和手机端一样的设计方案可能不太合适,尤其是为移动端单独设计的产品。

如果要支持平板电脑,在设计阶段就应该把各种可能的屏幕大小考虑进来。

5. 度量单位

我们使用像素来表达尺寸的大小,像素可分为物理像素和逻辑像素。物理像素就是一个一个排列整齐的像素点,可以想象成由三个不同颜色的 led 组成的发光体。逻辑像素是一个虚拟的概念,一个逻辑像素单位可能由真实的多个物理像素表达出来。像素的定义

5.1 Px 的意义

我们在浏览器中使用的尺寸单位 px,也称 CSS 像素,是一种与设备无关的逻辑像素。

我们在使用不同设备输出时,眼睛与设备输出的典型距离是不同的。确切地说,px 是一个视角单位,1px 即为从一臂之遥看解析度为 96DPI 的设备输出(即 1 英寸 96 点)时,1点(即 1/96 英寸)的视角。浏览器会根据设备的典型使用距离计算出 1px 到底应该占用几个物理像素,这种占比关系可以表示为设备像素比 devicePixelRatio。

简单解释 1px 对于用户的意义,那就是如果用户按设备的典型距离观看设备上展示的内容,1px 对用户的主观感受是差不多的。

5.2 相对单位 rem/vw/vh/vmin/vmax

相对单位 rem/vw/vh/vmin/vmax 这些都是实现等比缩放的方式。

  • rem: 相对根元素的字体大小的比例。在实现上,一般先由 Js 根据屏幕宽度给根元素设置 font-size,页面其它元素都使用 rem 做为度量单位。
  • vw:视窗宽度的百分比,1.25vw 代表视窗的宽度(即 window.innerWidth)的 1.25%
  • vh:视窗高度的百分比
  • vmin:当前 vw 和 vh 中较小的一个值
  • vmax:当前 vw 和 vh 中较大的一个值 Rem 方案的起源:因为当年 viewport 在低版本安卓设备上有兼容问题,而 vw/vh/vmin/vmax 也有少部分不兼容,所以流行用 rem 来模拟 vmin 实现在不同设备等比缩放的「一竹竿」方案。

现在 vw/vh/vmin/vmax 在各浏览器的支持度已经很好了,曾经流行的 flexible 库也已经弃坑。若无需支持低端设备,果断使用 vw/vh/vmin/vmax 实现等比缩放。

5.3 用 px 还是 相对单位?

一言以蔽之:UI 设计师说了算。为什么很多项目还是使用 px?

用 px 还是相对单位,这个问题实质上是用 px 还是等比缩放。对用户来说,就是「同样观看距离情况下,大屏看的更多还是大屏看的更大」? 看得更大: 看得更多: 如果只用相对单位或者只用 px,都属于一刀切。建议根据实际情况做选择,和设计师多沟通。大部分时候,使用「Px + 各种布局手段」为主「vx,vxxx+媒体查询」为辅的方案。

6. 跟设计师沟通

6.1 解读设计稿

设计师在设计移动端时最常用到的是 ios 的设计规范,是基于 iphone 6 的,iPhone 6 宽度的逻辑像素是 375px,dpr 是 2。

设计稿按宽度对 375 的倍数,分为 1 倍图,2 倍图,3 倍图,宽度分别是 375, 750, 1125。在换算成 px 的时候,只需要用设计图上的尺寸单位除以倍数 x 即可。以 2 倍图为例,此时设计图的宽度是 750,将图中的尺寸除以 2,就得到对应的逻辑像素 px。也有的设计工具会直接提供逻辑像素,省了研发做单位换算的过程。 如果设计稿宽度并不是 375 的倍数怎么办?最简单的方法,是将设计图的宽度除以一个数 x,使得出来的商在 360 - 414 之间,这个图就是 x 倍图。当然,具体的还是要跟设计师沟通。

6.2 单位换算

首先和设计师确认哪些地方是等比缩放,哪些地方是用 px。设计稿到实现涉及到的单位换算,可以借助 less 等 CSS 处理器,实现 px2vm,px2px 等功能。

// 假设设计稿的宽度是 750
@function px2vw($px) {
  @return $px / 750 * 100vw;
}

@function px2px($px) {
  @return $px / 2;
}

7. 可能的坑

技术在发展,这些坑随时都可能过时,所以仅供了解。当遇到坑的时候,你要相信你不是第一个踩坑的人。

7.1 延迟点击

移动端用户触碰一次屏幕会同时触发 touch 和 click 事件,touch 事件执行的优先级比 click 高。但是click 事件要在 300ms 以后才生效,以确定是单击还是双击,在某些特点条件下容易造成点击穿透现象。假设一个蒙层关闭按钮绑定的是 touch 事件,点击蒙层的关闭按钮,蒙层消失后会触发关闭按钮下面元素的 click 事件。

解决方案比较多,有一种是在 touch 事件回调中调用 e.preventDefault() 来阻止系统触发 click 事件。有的系统可以取消延迟点击,具体细节可以参考 300ms tap delay, gone away

For many years, mobile browsers applied a 300-350ms delay between touchend and click while they waited to see if this was going to be a double-tap or not, since double-tap was a gesture to zoom into text.

....

Ever since the first release of Chrome for Android, this delay was removed if pinch-zoom was also disabled. However, pinch zoom is an important accessibility feature. As of Chrome 32 (back in 2014) this delay is gone for mobile-optimized sites, without removing pinch-zooming! Firefox and IE/Edge did the same shortly afterwards, and in March 2016 a similar fix landed in iOS 9.3.

你只需在 head 中做如下配置:

<meta name="viewport" content="width=device-width" />

7.2 刘海屏

IPhone X 取消了物理按键,改成底部小黑条,全屏显示。 对此,iOS 11 上新增了 4 个预定义变量,用于设定安全区域与边界的距离。参考链接 这已经成为标准

// HTML
<meta name="viewport" content="... viewport-fit=cover">

// CSS
body {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

7.3 高清图

UC 浏览器(Android)会出于性能的考虑而不在移动端显示高分辨率的图片。

7.4 单击放大

如果没有做理想适配,点击某个可以 Focus 的元素时,屏幕会以这个元素为中心放大。 有一种解决方案是利用 js,在 Focus 时禁止缩放,Blur 后再允许缩放。

7.5 苹果手机的虚拟键盘

IOS 的虚拟键盘打开时,定位为 position:fixed 的元素会失效,导致位置被虚拟键盘挤上去,或者会有一个闪动。解决方案参考 这里