1、困扰多时的问题

在这之前做Web App开发的的时候,在自适应方面一般都是宽度通过百分比,高度以iPhone6跟iPhone5之间的一个平衡值写死,我们的设计稿都是iPhone5的640 * 1136标准,所以高度一般取个大概值,各种图标的宽高也是取平衡值写死,然后部分样式通过媒体查询来设置,例如背景图的多倍图、基础字体大小、图标宽高。

这样做的弊端很明显:

  • 做出来的页面在各种手机端看起来的物理大小(高度)是一样的,所以在大屏手机会觉得页面稍小,小屏手机页面稍大

  • 如果要使高度能更好的适应各种手机屏幕,需要写太多的媒体查询样式,效率低下

  • 全屏背景图片跟页面元素需要耦合时,元素位置的确定尤为困难(可能需要通过百分比去确定元素的横向位置,但始终会有误差)

...

最近在微博上看到流云诸葛总结的一篇文章《从网易与淘宝的font-size思考前端设计稿与工作流》,其中介绍到的几种Web App适配方案,我们现在的做法恰好是跟拉勾网类似的简单方案,当然就会有上面我提到的一些问题,最后经过预研和demo测试,我们采取了网易跟淘宝的方案,其实这两者的方案是大同小异,都是基于rem的适配方案。

2、解决问题的方案

网易跟淘宝的方案介绍在上面流云诸葛的文章中已经写的很清楚了,建议可以先看看那篇文章再阅读下面我所说的,可能会更加清晰。

(1)方案的简单介绍: 基于rem

前提:页面元素的布局尺寸全都以设计稿为基准等比例设置。

给html根节点设置一个基础font-size值,然后页面的所有元素布局均相对于该font-size值采用rem单位设定。那么基础的font-size值该如何取呢?

假如通过媒体查询设置font-size,只能解决一部分的情况,而且并不能完成适配,因为手机屏幕宽度类型实在太多了,所以font-size的取值要通过js计算,取当前viewport的deviceWidth与设计稿的宽 的 比例值,例如:我们的设计稿尺寸都是640px的,iphone5的deviceWidth是320px,那么计算出来的font-size值就是 320 / 640 = 0.5,因为得出的font-size太小,不方便计算,且有的浏览器可能不兼容太小字号,所以将font-size放大100倍,所以最终计算出来的font-size为 320 / 640 * 100 = 50(px); 当然,这个值是根据设计稿来计算的,所以根据计算规则,下面列出几种常见设计稿相应的font-size值:

  

deviceWidth = 320,font-size = 320 / 6.4 = 50px
deviceWidth = 375,font-size = 375 / 6.4 = 58.59375px
deviceWidth = 414,font-size = 414 / 6.4 = 64.6875px
deviceWidth = 500,font-size = 500 / 6.4 = 78.125px

可在script标签加上如下代码

(function () {
    document.addEventListener('DOMContentLoaded'function () {
        var html = document.documentElement;
        var windowWidth = html.clientWidth;
        html.style.fontSize = windowWidth / 6.4 + 'px';
        // 等价于html.style.fontSize = windowWidth / 640 * 100 + 'px';
    }, false);
})();
 
// 这个6.4就是根据设计稿的横向宽度来确定的,假如你的设计稿是750
// 那么 html.style.fontSize = windowWidth / 7.5 + 'px';

至此,font-size的基础值就确定好了,而且知道该font-size值是手机deviceWidth跟设计稿的比例值 的 100倍(重要)

(2)那么页面元素该如何设置宽高、边距

例如:一个设计稿宽高为140px的图标,左边距为50px,那么它的css应该这样写

1
2
3
4
5
.icon {
    width: 1.4rem; /* 像素换算rem:140px / 100 = 1.4rem */
    height: 1.4rem;
    margin: 0 0 0 .5rem;
}

因为html的font-size是放大了100倍,所以计算rem时,要用设计稿的实际像素除以100,140px / 100 = 1.4rem; 最后实际的像素大小就会由deviceWidth跟设计稿的横向宽 的 比例 自动计算出来。

如图iPhone5下面的效果:

iPhone6的效果:

可以看出来:html的font-size动态根据deviceWidth改变,图标的宽高、边距等也根据font-size动态按比例变化,大功告成了?不对,相信机智的你已经看到貌似在iPhone6的下有的图标背景错位了。。是的,这暴露出了一个背景使用雪碧图的一个弊端(由于font-size小数点太多,计算出实际背景图大小background-size跟背景图位置background-position时浏览器精度不够可能就会出现位置的偏差(我猜的),这个后面还会详细讲解决方案)

到这里,设置宽高、边距等都OK了,接下来...

(3)其他元素的字体大小该如何设置?

在流云诸葛的文章中讲到,网易跟淘宝的做法都是使用额外的媒体查询设置几种字体大小,例如:

1
2
3
4
5
6
7
8
9
10
11
12
@media screen and (max-width: 320px) {
    body{font-size: 14px;}
}
@media screen and (min-width: 321px) and (max-width: 413px) {
    body{font-size: 16px;}
}
@media screen and (min-width: 414px) and (max-width: 639px) {
    body{font-size: 17px;}
}
@media screen and (min-width: 640px) {
    body{font-size: 18px;}
}

可为什么不用rem呢?后来去查了一番资料,发现有一种叫做点阵字体的存在(什么是点阵字体),也叫作位图字体,位图我们都知道,跟矢量图是有区别的,就是放大会模糊,所以点阵字体也是放大会模糊的,如果根据rem设置字体大小,字体会自由缩放,可能就会导致点阵字体模糊,所以需要设定使用几种固定大小的字体。不过,在正常情况下,系统自带的字体都是矢量字体,所以使用rem为单位是没有问题的,除非你的网页需要用到特殊的点阵字体。

总结:如果网页没有用到特殊的点阵字体,字体单位使用rem,如果用到了点阵字体,字体需要通过媒体查询设置几种固定大小的字体

(4)关于背景图片的错位问题

上面已经发现了,通过换算rem设置background-size跟background-position的时候,在一些手机型号下会出现背景图错位的情况,可是如果不用rem设置的话,又不能达到适配的目的。(background-size、background-position的rem换算方法跟前面讲的宽高设定一样,都是设计稿尺寸(这时应该是雪碧图的原始尺寸)除以100倍)

最后经过尝试,得出了几种解决方案:

1)如图(推荐方案):

图标的样式

1
2
3
4
5
6
7
8
9
10
.icon {
    width: 1.4rem;
    height: 1.4rem;
    background-image: url(sprite.png);
    background-repeat: no-repeat;
    background-size: 1.4rem;
}
.icon3 {
    background-position: 0 -2.8rem;
}

解决方法,如图:

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.icon-fix {
    background: none;
    position: relative;
    overflow: hidden;
}
.icon-fix:after {
    content: '';
    display: block;
    width: 10000%;
    height: 10000%;
    position: absolute;
    left: 0;
    top: 0;
    background-image: url(sprite.png);
    background-repeat: no-repeat;
    background-size: 140rem;
    -webkit-transform-origin: 0 0;
    -webkit-transform: scale(.01);
    transform-origin: 0 0;
    transform: scale(.01);
}
.icon3:after {
    background-position: 0 -280rem;
}

所有相关代码(传送门)。

2)不使用雪碧图,使用单个背景图,这个时候就不存在background-position的需要,只需设定background-size: contain;即可,这样做的弊端就在于无法使用雪碧图,图片请求增多,适用于页面图标较少的情况

3)使用嵌套img标签,通过绝对定位模拟background-position,具体请看 responsive-sprites,这种做法需要更多的标签,且img图片只能放图标尺寸大小一样的雪碧图,而且不能通过媒体查询使用多倍图

以上3中解决方案第一种最优,当然有些特殊情况可能需要按需选择!

最后发现一篇研究rem产生小数点像素的问题的文章,感兴趣的可戳 《rem 产生的小数像素问题

转自 : http://www.cocoachina.com/webapp/20151110/14148.html

移动端Web App自适应布局探索的更多相关文章

  1. 移动端web app自适应布局探索与总结

    要掌握的知识点: iphone6 屏幕尺寸为 375*667 (pt)也就是 网页 全屏显示时候 document.documentElement.clientWidth------可以理解为屏幕越大 ...

  2. web app 自适应方案总结 关键字 弹性布局之rem

    关于rem,主要参考文档 1.腾讯ISUX (http://isux.tencent.com/web-app-rem.html) 2.http://www.w3cplus.com/css3/defin ...

  3. web app 自适应方案总结 弹性布局之rem

    关于rem,主要参考文档 1.腾讯ISUX (http://isux.tencent.com/web-app-rem.html) 2.http://www.w3cplus.com/css3/defin ...

  4. web app 自适应 弹性布局之rem

    关于rem,主要参考文档 1.腾讯ISUX (http://isux.tencent.com/web-app-rem.html) 2.http://www.w3cplus.com/css3/defin ...

  5. 【饿了么】—— Vue2.0高仿饿了么核心模块&移动端Web App项目爬坑(三)

    前言:接着上一篇项目总结,这一篇是学习过程记录的最后一篇,这里会梳理:评论组件.商家组件.优化.打包.相关资料链接.项目github地址:https://github.com/66Web/ljq_el ...

  6. 移动端web app要使用rem实现自适应布局:font-size的响应式

    关于webAPP的开发最主要解决的就是“自适应自适应布局”.常规的适配有很多做法,例如:流式布局.限死宽度等,但是这些方案都不是最佳的解决方法​,而最满足设计需要的是: 元素可以根据屏幕大小而等比列变 ...

  7. 移动端web app开发学习笔记

    移动web和pc端web以及web app 移动web开发跟web前端开发差别很小,使用的技术都是html+css+js.手机网页可以理解成pc网页的缩小版加一些触摸特性.在浏览器中进行的网页开发,最 ...

  8. 移动端web app开发备忘

    近期要做个手机html5的页面,做些知识储备,重要的点记录下来以备兴许. 1.devicePixelRatio:定义设备物理象素和设备独立象素的比例.css中的px能够看作是设备的独立象素.通过dev ...

  9. 利用float与overflow:hidden实现移动端两栏自适应布局

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. MyFirstStruts2

    package com.sdlc.action; public class HelloWorldAction { private String msg; public void setMessage( ...

  2. qt info.plist 添加

    http://www.waitingfy.com/archives/1242 http://www.sollyu.com/settings-icon-under-the-qt-mac-applicat ...

  3. shell 中如何判断前一个命令是否执行成功

    shell 中如何判断前一个命令是否执行成功 通过判断返回值来解决: if [ $? -eq 0 ];then 命令正确的分支 else   命令失败的分支 fi

  4. 【转】Android 源码下利用jni编译自己的项目(参考系统development/samples/SimpleJNI)

    原文网址:http://blog.csdn.net/qiuxiaolong007/article/details/7860481 记于正文前:环境是ubuntu10.10,android 源码是2.0 ...

  5. yum 配置详解(转发)

    一.yum 简介 yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发行版的 ...

  6. Remove Invalid Parentheses 解答

    Question Remove the minimum number of invalid parentheses in order to make the input string valid. R ...

  7. 【编译原理】语法分析LL(1)分析法的FIRST和FOLLOW集

    近来复习编译原理,语法分析中的自上而下LL(1)分析法,需要构造求出一个文法的FIRST和FOLLOW集,然后构造分析表,利用分析表+一个栈来做自上而下的语法分析(递归下降/预测分析),可是这个FIR ...

  8. Node.js-require的使用方法

    require最常用的方法 require('http') 内置模块 require('./server')  “./”表示当前路径,后面跟的是相对路径 require("../lib/se ...

  9. Yii2 分页类的扩展和listview引用

    Yii2 本身提供了不错分页选项供用户设置,但是实际项目中我们往往需要复杂一些的分页样式,例如下图所示的效果,上下翻页可用和不可用均用图标来替换.

  10. php 的设计模式

    1.单例模式 单例模式顾名思义,就是只有一个实例.作为对象的创建模式, 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式的要点有三个: 一是某个类只能有一个实例: ...