移动端页面切图自适应方案和体验优化经验

最近在做活动页切图时,遇到了针对不同尺寸移动设备屏幕适配的问题。相信这个问题是有移动端前端开发经验的攻城狮们都遇到过的。再加上一些优化体验,这里简单写一些经验。

像素完美

像素完美是UI设计师的终极目标之一(其余的还有分辨率无关,多平台体验一致等)。但是切图中不可避免地会使用到类似background-image这样设置背景CSS样式的属性,之后再将一些交互元素通过绝对定位或是其他方式放在它视觉上应该出现的位置。在移动端设备宽度不一时,交互元素的位置如何保值像素完美的一致呢。

最容易想到的方法是百分比布局,保证设计师设计的美美的UI界面可以自适应地等比扩充到整个页面。不过这样会让交互元素的位置摆放很难办,难以保证设备兼容性。flex布局也是种常见的解决方案,但距离像素完美还有距离。

于是,我在上一次实践中,采用了固定宽度的处理方式(这并不是一种好的实践),CSS样式写起来大概是下面这样的。

1
2
3
4
5
6
7
8
9
10
.container {
display: block;
width: 414px;
margin: 0 auto;
}
.bkg {
background-image: url('./bkg.png');
background-size: 100%;
background-repeat: repeat-y;
}

margin: 0 auto是为了保证PC端居中的兼容性。这么写可以让交互元素定位时没有了设备宽度不同的后顾之忧。不过,在页面打开后,宽度较大使得页面出现横向滚动条,在绝大多数的移动端页面都不是种好的体验。的确,可以在meta标签中,设置user-scalable=yes来实现宽度上的自适应。但是,放开了页面缩放的限制也不是好的实践方式。

这次活动页参考的使用rem的方式(淘宝最早实践的)是一种明显更好的方法。rem是CSS3中出现的新属性,它是root em的缩写。和em不同的是,rem使用整个html的font-size作为尺寸的参考。只需要改变html的font-size,所有使用了rem属性的元素大小都会等比例地变化。于是,下面的一段代码轻松地实现了移动端的自适应方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function(win, doc){
var docEl = doc.documentElement,
resizeEvt = 'onorientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 750) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
};
//省去addEventListener兼容性处理
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(window, document);

代码里假设UI设计稿原始宽度为750px。大意是:

  • 页面宽度超过750px时,document的字体大小恒为100px,此时页面中涉及尺寸的CSS样式部分统统用{像素值} / 100 rem书写。之所以使用100px正是为了换算时方便
  • 页面宽度小于750px时,document等比缩小字体大小,页面中使用rem的元素都会等比缩小。从而保证交互元素不错位。

效果类似淘宝手机站。使用rem布局需要注意:

  • <head>中放置这段代码,保证在页面元素渲染前确定font-size大小,避免闪屏现象出现影响体验。
  • PC端可以使用媒体查询rem在移动端使用较多
  • rem方案可以使用在页面的一部分,在宽度固定的元素中使用flex这样的方案

用户体验

上个活动页中遇到了一些优化体验的小地方,列在下面。

  • 禁止用户选中页面元素。这么做可以避免长按屏幕的选中,很明显地提升体验。
    1
    2
    3
    4
    5
    6
    7
    8
    body {
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -khtml-user-select: none;
    user-select: none;
    margin: 0 auto;
    }
  • 禁止一些手机上为手机号码和邮箱地址进行的特殊处理
    1
    2
    <meta name="format-detection" content="telephone=no">
    <meta name="format-detection" content="email=no">
  • 禁止页面缩放,很常见的需求
    1
    <meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
  • 为二维码单独切图,可以解决长按二维码无法识别的问题
  • 输入框获得焦点时自动上移。可以通过document.scrollTop或设置输入框部分position:fixed实现