活动端H5页面适配难点切磋,移动端适配

rem 产生的小数像素问题

2015/11/05 · CSS · 1 评论 · rem

原文出处: 淘宝前端团队(FED)- 颂晨   

图片 1

由于日常需求以无线居多,所以可以在业务中做一些尝试,如 rem,刚接触这个特性的时候,曾经一度爱不释手,仿佛在无线开发的坎坷路上寻找到一条捷径。然而随着使用范围的扩大,慢慢的发现了一些使用 rem 带来的问题。

适配是什么:在不同尺寸的手机设备上,页面相对性的达到合理的展示(自适应)或者保持统一效果的等比缩放(看起来差不多)

移动端适配

刚开始做移动端web开发的同学应该都碰到过页面适配问题,为什么我在开发手机上调试好的页面在其他手机会有这样或那样的样式问题?viewport我也设置了,为什么还是显示不正常?难道我要为每种手机屏幕写媒体查询,有没有简单的方式,可以不用关注手机屏幕的差异性呢?

rem

关于 rem 这个单位的介绍,在此就不赘述,有兴趣的同学可以阅读一丝的《响应式十日谈第一日:使用 rem 设置文字大小》,文章对 rem 进行了详细的介绍。


通过rem适配

  • em: 根据元素自身的字体大小来计算自己的尺寸

  • rem: (root em) 根据根节点(html)的字体大小来计算自己的尺寸

  我们知道,在不同的手机设备,分辨率大小是不一样的。为了使页面在不同分辨率下等比缩放,需要动态的设置Html的字体大小来达到页面等比缩放的效果。我们可以如下设置rem值:

    function() {
        var html = document.querySelector("html");
        var width = html.getBoundingClientRect().width;
        html.style.fontSize = width / 16   "px";
        //  width / 16  html的字体大小 = 屏幕宽度的16分之一 = 1rem 
    }

注意: 因为页面的字体大小最小为12px,因此要保证rem不小于12

百度中搜索移动端H5页面适配关键字,大概可以得到180多万的搜索结果,由此可见这个问题也得到很多人的关注。本文的目的主要是分析解决移动端H5页面适配问题过程中牵扯到的知识点,然后梳理分析目前常见的适配解决方案。

用途

在无线开发中,响应式布局尤为重要,先不说屏幕尺寸越来越多样化的 iPhone,单是安卓就有 N 多种尺寸要适配。

在没有使用 rem 之前,想要按照设计师的想法去适配不同 分辨率1 是一件非常难操作的事情。用了 rem 以后,一切简单了许多,你可以用它来设置元素的宽高、间距…,然后针对不同的分辨率计算并设置相对应的根字体大小,然后元素就好像缩放过一样自动适应了当前的分辨率,大大的降低了适配工作量。

Demo:

图片 2

上图是同一个页面在 Apple iPhone 5 和 Samsung Galaxy S4 两款机器下的效果,可以看出从 320px 宽的 iPhone 5 到 360px 宽的 S4,图片像是等比放大了一样,我们分析下这个原理:

假定2 width=320px 的分辨率下的根字体大小是 32px,由此推算:

  • width=320px 分辨率下:

    根字体大小是 32px,该分辨率下宽 1rem 的元素在浏览器里的真实宽度就是 1 * 32 = 32px;

  • width=360px 分辨率下:

    如果要达到等比放大的效果,宽 1rem 的元素在浏览器里的真实宽度就应该是 32 * (360/320) = 36px,由此得出 width=360px 分辨率下的根字体大小为 36px;

由此可见等比缩放是通过控制根字体大小来实现的,且根字体大小与屏幕宽度成正比。

适配元素:

1.字体

2.宽高

3.间距

4.图像(图标、图片)  --比较复杂


通过viewport适配

  移动设备上的浏览器都会把自己默认的viewport设为980px或1024px(也可能是其它值,这个是由设备自己决定的),但带来的后果就是浏览器会出现横向滚动条,因为浏览器可视区域的宽度是比这个默认的viewport的宽度要小的。

devicePixelRatio

   在移动端浏览器中以及某些桌面浏览器中,window对象有一个devicePixelRatio属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。css中的px就可以看做是设备的独立像素,所以通过devicePixelRatio,我们可以知道该设备上一个css像素代表多少个物理像素。例如,在Retina屏的iphone上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素。但是要注意的是,devicePixelRatio在不同的浏览器中还存在些许的兼容性问题。

ideal viewport

  移动端的viewport分为layout viewport 、 visual viewport 和 ideal viewport 三类。其中的ideal viewport是最适合移动设备的viewport,ideal viewport的宽度等于移动设备的屏幕宽度,只要在css中把某一元素的宽度设为ideal viewport的宽度(单位用px),那么这个元素的宽度就是设备屏幕的宽度了,也就是宽度为100%的效果。

把viewport宽度设置为 ideal viewport 的宽度

  只需要把width设为width-device这个特殊的值。通过width=device-width,所有浏览器都能把当前的viewport宽度变成ideal viewport的宽度,但要注意的是,在iphone和ipad上,无论是竖屏还是横屏,宽度都是竖屏时ideal viewport的宽度。

也可以设置initial-scale=1达到同样的效果,缩放是相对于ideal viewport来缩放的:

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

如果 width 和 initial-scale=1同时写的话,浏览器会取它们两个中较大的那个值。同时 initial-scale=1 解决了 iphone、ipad的毛病,width=device-width则解决了IE的毛病:

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

注意:在iphone和ipad上,无论你给viewport设的宽的是多少,如果没有指定默认的缩放值,则iphone和ipad会自动计算这个缩放值,以达到当前页面不会出现横向滚动条(或者说viewport的宽度就是屏幕的宽度)的目的。

由于本文内容较长,下面先给出文章的提纲:

小数像素

刚才举的例子里面 1rem 在 width=320px 分辨率下的真实尺寸为 32px,在 width=360px 分辨率下的真实尺寸为 36px,均为整数。

如果是 1.75rem 呢?

代表机型 浏览器宽 对应尺寸
iPhone 4/4s/5/5s 320px 56px
Samsung Note 3, Nexus 5… 360px 63px
iPhone 6 375px 65.625px
Google Nexus 6 412px 72.1px
iPhone 6 Plus 414px 72.45px

可以看到部分机型下出现了小数像素,那么浏览器是如何处理小数像素的呢?

图片 3

如图,第一组每个色块的大小为 1.75rem x 1.75rem,第二组每个色块的大小为 1.85rem x 1.85rem;

图片 4

先看第一组色块,在 iPhone 6 下,其在浏览器内的渲染尺寸应该是 1.75 * 37.5 = 65.625px;

图片 5

但真实渲染尺寸却是另外一种情况:有的宽度是 66px,有的却是 65px,而且顺序上毫无规律。

这一结果让我十分疑惑,如果浏览器统一做四舍五入处理,那么所有的色块尺寸也应该是一样的,不会出现部分向上取整,部分向下取整。

思考许久无果,大胆设想了一下:浏览器在渲染时所做的舍入处理只是应用在元素的渲染尺寸上,其真实占据的空间依旧是原始大小。

也就是说如果一个元素尺寸是 0.625px,那么其渲染尺寸应该是 1px,空出的 0.375px 空间由其临近的元素填充;同样道理,如果一个元素尺寸是 0.375px,其渲染尺寸就应该是 0,但是其会占据临近元素 0.375px 的空间。于是就顺着这个思路验证了以下:

  1. 第一个色块的宽度为 65.625px,根据四舍五入的原则其最终渲染尺寸为 66px,空出的 0.375px 由第二个色块补上;
  2. 第二个色块向左补进 0.375px,相当于减少了 0.375px,余下 65.25px,根据四舍五入的原则其最终渲染尺寸为 65px,多出的 0.25px 会占用第三个色块的空间;
  3. 第三个色块被占用了 0.25px,相当于增加了 0.25px,等于 65.875px,根据四舍五入的原则其最终渲染尺寸为 66px,空出的 0.125px 由第四个色块补上;
  4. 第四个色块向左补进 0.125px,相当于减少了 0.125px,余下 65.5px,根据四舍五入的原则其最终渲染尺寸为 66px,空出的 0.5px 由第五个色块补上;
  5. 第五个色块向左补进 0.5px,相当于减少了 0.5px,余下 65.125px,根据四舍五入的原则其最终渲染尺寸为 65px,多出 0.125px;

上述验证与浏览器输出结果完全一致,表明浏览器在处理小数像素的时候并不是直接舍入处理的,元素依旧占据着应有的空间,只是在计算元素尺寸的时候做了舍入处理(后来在看到LayoutUnit – WebKit 这篇文档后,也印证了之前的假设)。

你可以参考上述原理对第二组色块进行验证,然后比对结果。

适配的方法:

1.百分比适配

         百分比布局问题:

                  1.百分比的值不好计算

                  2.需要确定父级的大小,因为要根据父级的大小进行计算

                  3.宽度可以设置,但是高度不好设置

         总结:一般情况下百分比布局是需要配合其他的布局而使用


2.比例缩放适配

         把所有机型的设备独立像素设置成一致的(以前淘宝使用过这种方法)

                  1.viewport需要通过js动态设置(不能直接把device的值设置成数值)

                  js代码:

```

                      (function(){

                          /**

                          以iPhone6 plus为例子:

                          原来的尺寸:  curweidth 414

                          要变成的尺寸:targetwidth 375

                          比例:scale  ?

                          换算scale方法:

                          如:414/比例=375

                          那么:比例=414/375

                          所以:scale=curweidth/targetwidth

                          */

                          varcutWidth = window.screen.width;

                          vartargetWidth = 375;

                          varscale=curWidth/targetWidth;

                          varmeta = document.createElement("meta");

                          meta.name='viewport';

                          meta.content='initial-scale=' scale ',minimum-scale=' scale ',maximum-scale=' scale '';

                          document.head.appendChile(meta);

                  }()

```

                  2.通过设置比例(初始比例以及缩放比例),把宽度缩放成一致的

                  代码:

                  注意:viewport里给了缩放值以后,最终的页面的宽度是原来的值除以缩放比例

                  缺点:

                  1.就像viewport设置宽度的时候,可以吧宽度设置成一个固定值一样,会出现所有手机看上去都是同样的小没有分别了,不太好

                  2.算出的值在一些有小数的情况下可能会出现误差(无关紧要),因为设备独立像素不能有小数


3.viewport适配

         比例缩放适配:根据dpr的值,吧饰扣进行缩放,缩放到wuli像素,也是把屏幕的尺寸直接设置成它对应的物理像素。(淘宝在用,不过他只处理了dpr为2的几个设置,以及iPhone6 plus)

         缺点:

         1.这种方法有时候不准确,比如dpr不为整数的时候,会出现除不尽的情况,那缩放的倍数会出现很长的小数,再去算物理像素的时候就会有误差

         2.如果屏幕的分辨率是非标准的话,算出的物理像素就是非标准的。

         /**

         同上个方法类似

         */

         js代码:

                  varscale=1/window.devicePixelRatio;

                  varmeta = document.createElement("meta");

                  meta.name='viewport';

                  meta.content='initial-scale=' scale ',minimum-scale=' scale ',maximum-scale=' scale '';

                  document.head.appendChile(meta);

         }()


4.rem适配

什么是rem适配:

         px:绝对单位,给多少就是多少

         问题:不管屏幕尺寸怎么变化,它都不会变,做不到适配

         em:相对单位,相对于自身字体大小的值

         font-size:12px  1em=12px

         问题:

                  1.chrom下有最小字体限制,必须为12px,所以这个值不能小于12

                  2.如果两个一样的元素,但是里面字体不一样,那就不能

                  统一设置了,或者元素字体变化了,就又要统一设置一遍

         rem  CSS3新增的一个相对单位,相对于根节点(HTML)字体大小的值

                  r  root

                  html{font-size:10px}    2rem=20px

                  通过它就可以做到只修改根元素的大小,就能成比例地调整所有的字体大小,只依赖html字体的大小

1.适配的基础知识

1.1理解移动端单位
 1.2理解viewport

问题

目前遇到最多的问题就是 background-image 的问题,经常会因为小数像素导致背景图被裁掉一部分。

图片 6

上图是同一组 icon 在不同机型下的效果,可以看出这些 icon 在 iPhone 5 和 Galaxy S4 下或多或少的会被裁掉一部分,原因就是由于小数像素导致的,这点可以从元素的Computed Style 上看出。

2.页面中那些内容需要适配

2.1图片高清适配
 2.2字体大小适配
 2.3布局宽度适配

解决

如何避免这种问题呢?以下两点建议:

  • 使用 iconfont;
  • 如需使用 background-image,尽量为背景图设置一定的空白间隙,如图:

图片 7

3.适配解决方案分析


---这里是分隔符,正文开始---

小结

小数像素产生的问题不单单只有 background-image,还会有其他尚未遇到的坑,然而在了解了浏览器是如何处理小数像素的原理以后,此类问题就变得很好解决,也非常可控。

1.适配的基础知识

注:

  1. 文中出现的分辨率都是指浏览器分辨率,关于逻辑分辨率、物理分辨率之间的关系可以参考:「像素」「渲染像素」以及「物理像素」是什么东西?它们有什么联系?;
  2. 为了保证大部分分辨率下计算出的根字体大小都为整数,所以约定根字体大小的计算公式为:分辨率宽度 / 10;

    1 赞 3 收藏 1 评论

图片 8

1.1理解单位

px、pt、pc、sp、em、rem、dpr、dp、dip、ppi、dpi、ldpi、mdpi、hdpi、xhdpi、xxhdpi

不知道正在看文章的你对上面列出来的这些单位是不是很熟悉,如果是的话,就可以跳过了。

理解这些单位的用法以及区别,对理解移动端页面适配有很大的帮助。为了让你对上面的单位有个大体的认知,这里把上面的单位分成了三类:

  • 如果你是ios开发,你需要了解的单位:pt,px,ppi;实际开发中用到的单位:pt。
  • 如果你是android开发,你需要了解的单位:dip/dp,sp,px,dpi/ppi,ldpi,mdpi,hdpi,xhdpi,xxhdpi;实际开发中用到的单位:dp,sp。
  • 如果你是前端开发,你需要了解的单位:px,em,rem,dpr;实际开发中用到的单位:px,em,rem,dpr

下面分别对每个单位展开分析:

*** dpi / ppi ***

** dpi ** , dot per inch ,每英寸的点数;打印或印刷领域使用的单位,代表打印机每英寸可以打印出的点数 。

ppi, pixel per inch ,每英寸的像素数,像素密度;表示图像或者显示器单位面积上像素数量。

dpippi 都是描述分辨率的单位,但是两者是有区别的,但是在描述手机分辨率时,可以认为两者意义相同,以前android设备偏向于使用dpi,ios设备偏向于使用ppi,目前android和ios统一使用ppi描述手机屏幕的像素显示密度。

ppi的计算方法:

计算ppi

*** ldpi、mdpi、hdpi、xhdpi、xxhdpi ***

android对移动设备不同屏幕分辨率的分类。

屏幕分辨率分类

*** pt,pc,sp ***

** pt ** ,磅(point的音译),印刷中使用的表示字型的大小单位,1inch = 72pt (印刷中这个关系成立,ios中不成立),ios开发中使用的逻辑单位,是和设备无关的单位。

** pc ** 印刷中使用的单位,1pc = 12pt,不需要关注。

** sp **, scale independent pixel ,android设备中用来显示字体大小的,和设备无关的尺寸,当设置字体大小单位为sp时,android系统字体大小会影响设置的字体渲染时的大小。

*** dip / dp ***

** dp/dip**, device independent pixel,表示设备独立像素,和设备无关的尺寸,相同的dp/dip值,不同设备展示的效果是一样的。

android使用的单位,之前偏向使用dip,目前建议使用dp。

android设备中,规定160ppi的屏幕,1dp = 1px;320ppi的屏幕,1dp = 2px,所以android设备中dp的计算方法:dp = px * (ppi / 160),这里的px是指设备的物理像素点。

和ios开发中用的pt单位类似。

*** px ***

** px ** ,像素,有两种像素概念,一种是网页设计中使用的css像素,一种是原生移动系统使用的物理像素。

作为css像素时,表示的也是一种设备无关单位,与android中使用的dp类似,默认情况下与系统分辨率下的像素大小相同,标清设备中,一个css像素和一个设备物理像素大小相同;在高清设备中,一个css像素可以大于或者等于多个设备物理像素,具体一个css像素,需要多少个物理像素来展示,浏览器会根据dpr计算。

原生移动系统中使用px单位时,表示的就是屏幕的物理像素点,每种屏幕的物理像素点大小可能不一样。

*** dpr ***

** dpr ** ,device pixel ratio, 横向或者纵向设备物理像素数量与设备独立像素数量的比值,浏览器中可以通过window.devicePixelRatio获取(存在兼容性问题)。

对于原生app,ios和android系统会自动根据dpr计算出渲染时需要的px值,最终不同屏幕上展示出来的大小很接近;而移动端页面渲染时想要做到这一点,就必须首先得到设备的dpr,然后再根据dpr计算渲染需要的px值。

ios设备中iphone3的dpr为1;iphone4,5,6,7的dpr为2;iphone6 ,7 的dpr为3。iphone6 和iphone7 实际计算出来的dpr应该时2.6左右,但是官方还是建议dpr为3,这是因为ios系统利用了一种“缩减像素采样”算法,自动缩减到2.6。

android设备中dpr值有多种,可知的有0.75,1,1.5,1.75,2,2.5,2.75,3,4等。

*** em,rem ***

** em ** 相对单位,CSS2引入的单位,作为字体大小使用时和百分比单位类似,都是相对于最近的父元素设置的字体大小,在body上设置字体大小为100%和设置字体大小为1em是一样的效果,默认情况下浏览器的字体大小为16px,这样只要浏览器默认得字体大小不变,1em = 16px。

** rem ** 相对单位,root em,CSS3新增的单位,作用和em类似,唯一的区别就是em是相对父元素的,rem是相对html根节点的,即所有使用rem单位的子元素的字体大小都是相对根节点的,所以使用rem可以避免使用em带来的子元素字体大小逐层复合的连锁反应。

更多关于em,rem的知识参见这篇文章理解web开发中的em单位和rem单位。

*** 分辨率 ***

平时说的手机屏幕分辨率,也称为物理分辨率或者原生分辨率,通常包括纵向分辨率和横向分辨率,例如iphone6的物理分辨率是1334 x 750,其中纵向分辨率是1334px,横向分辨率是750px,表示纵向方向可以显示1334个物理像素点,横向上可以显示750个物理像素点,这里描述分辨率使用的px单位,和css中使用的px单位意义不一样,这里代指物理设备的像素点。

还有一种分辨率叫做系统分辨率,例如iphone6的系统分辨率是667 x 375,其中高度是667pt,宽度是375pt,这里描述分辨率使用了pt单位,是一种设备无关单位。

屏幕尺寸相同的设备,物理分辨率越高,ppi也就越大,绝对单位面积上展示的物理像素数量越多,展示图片也就越细腻。

苹果把ppi > 300的屏幕称为视网膜屏,Retina屏。

1.2理解viewport

传统桌面web页面布局通常是定宽布局,但是定宽布局的方式对移动端却不适用,原因手机屏幕尺寸大小各异,定宽布局可能在某些手机上出现横向滚动条,导致阅读效果比较差。

为了让手机有更好的网页浏览体验,苹果引入了viewport,为页面提供了一个虚拟的布局窗口,在这个虚拟的布局窗口中渲染页面,然后系统会把渲染好的页面自动缩放到手机屏幕大小。

虽然viewport还没有成为正式的规范,但是现在绝大部分浏览器都支持viewport。

在桌面浏览器中,viewport严格等于浏览器窗口大小,页面渲染时,页面宽度不会超过浏览器的宽度。

移动端屏幕太窄,为了提供更好的页面体验,移动端提供了两种viewport:可视viewport布局viewport

可视viewport就是当前屏幕正在展示的区域,也就是移动设备屏幕的宽度,宽高通过window.innerWidth和window.innerHeight获取(存在兼容性问题)。

布局viewport,页面布局实际用到的viewport,通常比可视viewport要宽,宽高通过document.documentElement.clientWidth和document.documentElement.clientHeight获取。

移动端还有一种viewport概念,可以理解为理想viewport,作用就是在理想viewport下,不同移动设备,展示的字体大小接近,并且不需要用户缩放就可以展示全部的页面内容。

理想viewport的宽度默认等于可视viewport的宽度,但是对同一台设备来说,这个理想viewport的宽度是可以改变的,而可视viewport的宽度是不可变的。

如何使用理想viewport来布局页面呢?只需要设置viewport的width等于device-width。

viewport的属性,推荐使用以及支持度较广泛的属性只有6个:widthheightinitial-scalemaximum-scaleminimum-scaleuser-scalable

width 设置viewport布局宽度,内核是webkit的浏览器默认值是980px,取值范围在200-10000px,也可以取值为设备宽度device-width(等于横向设备无关像素数量)。

height 设置viewport布局高度,默认值依赖设备长宽比以及宽度值,取值范围在223-10000px,也可以取值为设备高度device-height。

initial-scale 设置初始缩放比例,页面第一次加载时的缩放比例。默认比例依赖于显示密度。在密度低于200 dpi的显示设备上,比例为1.0。在密度介于200及300 dpi之间的显示设备上,比例为1.5。对于具有300 dpi以上密度的显示设备,比例为密度/150 dpi向下取整的结果。取值范围由maximum-scale属性以及minimum-scale属性决定。如果设置initial-scale值为1,width默认是device-width,height默认是device-height

initial-scale设置的缩放大小会改变理想viewport的大小,不会改变可视viewport的大小,也不会改变布局viewport的大小,这是某些适配方案依赖的基本原理,也是解决1px问题的关键。后面分析适配方案时,动态viewport适配方案就依赖这个知识点。

maximum-scale 允许用户缩放到的最大比例,默认值是0.5,范围从0到10.0。

minimum-scale 允许用户缩放到的最小比例,默认值是5.0,范围从0到10.0。

user-scalable 用户是否可以手动缩放,值可以是:yes/true允许用户缩放;no/false不允许用户缩放。

2.页面中那些内容需要适配

2.1图片高清适配

图片适配的目的是为了在页面中可以高清还原设计图中用到的图片。

页面中用到的图片是否清晰和展示页面的硬件设备的dpr以及图片分辨率这两个因素有关,下面会通过三个例子来说明这个问题。

***示例一 ***

例如dpr=2的设备,1个设备无关像素(android中的1dp,ios中的1pt)需要4个设备物理像素点填充。对于尺寸为100 x 120 (px)的图片,如果用<img>来展示,图片显示时会产生模糊现象。

原因:渲染图片时,宽度是100px,所以横向会占用100个设备无关像素,高度是120px,所以纵向会占用120个设备无关像素,每个设备无关像素又需要2x2个物理像素点来填充,而图片在每个设备无关像素(px)单位上提供的像素点只有1x1个,这时,系统通过一定的算法在这1个像素点上就近取色,取到4个颜色(这4种颜色接近但是有一定区别)之后,当成4个像素点,然后填充到1个设备无关像素点上,这样就导致图片显示时模糊,dpr越大,这种方式显示的图片越模糊。

示例二

还是dpr=2的设备,但是准备了一个尺寸为200 x 240 (px)的图片,还是用<img>来展示,这时显示的图片就比较清晰了。

原因:这时图片本身可以在一个设备无关像素单位上提供2x2个物理像素点,设备展示图片时直接拿图片提供的像素点来填充就可以了,不用对像素点进行处理,所以可以比较清晰的显示图片。

示例三

还是dpr=2的设备,这次准备一个尺寸400 x 480 (px)的图片,还是用<img>来展示时,这种情况展示的图片缺少锐利度,也影响了图片的清晰度,但是很难看出来。

原因:图片本身在一个设备无关像素点单位上提供了4x4个物理像素点,而设备本身只需要2x2个物理像素点,所以会通过缩减采样算法,在图片提供的4x4个物理像素点中,选取颜色接近的2x2个物理像素点填充到设备无关像素点上,所以也会产生一定的色差,这种情况下图片尺寸越大,这种色差也就越明显,但是人眼很难区分这种色差。

有些现象靠文字描述可能无法体会

下面是我在oppo的一款手机上的测试结果,结合这张效果图就可以很好的理解上面的三个示例了:

图片 9

图片适配示例

图片适配最佳实践

要想高清显示图片,如果条件允许(有单独的图片服务器)最直接的解决办法,肯定是根据设备的dpr,为不同dpr的设备加载不同倍率大小图片显示;没这种条件的或者对用户体验没有很高要求的,只能选一种折中的方案了,一般情况下只需要提供布局尺寸2倍大小的切图就可以了,也就是只高清适配dpr=2的设备,但是dpr为3或者4的设备展示效果也能接受,不容易看出来模糊现象。目前主流机型的dpr也就在2和3之间。

2.2字体大小适配

字体适配目标主要还是看设计要求,主要有两种:

1.不同屏幕下,字体显示大小都一样,即需要等宽显示字体;

2.不同屏幕下,一行能显示的字数固定,即需要按比例缩放字体大小;

开始分析之前,先看下这两种字体适配的示例:

第1种字体适配方案的示例

图片 10

手机淘宝采用第1种方式适配字体

第2种字体适配方案的示例

图片 11

网易新闻采用第2种方式适配字体

下面就来具体分析下两种字体适配方案的原理以及优劣。

PS:为了方便分析和理解,下面的分析是基于的布局宽度等于设备宽度,即viewport的width=device-width的情况下分析的,其他布局宽度下的原理是类似的。

** 第1种字体适配方案原理 **

在开始分析这种方式的原理之前,先通过一张图理解下px和dp以及绝对长度之间关系。

px的绝对长度在不同设备下是不同的

由上图可知字体大小只与css单位px有关,而每个设备上px的绝对宽度又和设备的绝对宽度以及绝对宽度上划分出的设备无关像素点dp有关;只要设备的横向dp数量与绝对宽度的比值(dp/cm)相同,就可以保证px在不同设备上展示的绝对宽度是一样的;如果dp/cm的比值过大,那么px的绝对长度就会变小,看起来就会显小;如果dp/cm的比值过小,那么px的绝对长度就会变大,看起来就会显大;一般来说手机屏幕分辨率越高,相同px值的字体看起来就会越小。

iphone5和6的dp/cm比值十分接近,所以12px大小的字体在这两种手机上显示的大小基本一样,看不出来区别,但是iphone6 的dp/cm比值要比iphone5,6的略大,这就导致12px大小的字体在6 上显示的比5,6上显示的略小,上面的淘宝对比图仔细分辨可以看出来。

android的手机屏幕dp/cm比值在各个设备之间也有差异性,并且比较有多样性。所以同样12px大小的字体,各个设备显示时也是有差别的。

这种显示差别在iphone系列手机中可以忽略不计,但是android碎片化比较严重,完美兼容各种机型没有必要,主流机型中这种显示差别也可以忽略不计,所以采用这种方式进行字体适配只需要px值设置成一样的就可以了。

** 第1种字体适配方案优缺点**

优点:1.不同设备中字体大小显示一致,比较统一;2.大屏手机可以显示更多的文字;

缺点:1.由于单个字体宽度是定死的,所以在有些机型下可能会影响页面布局;

** 第2种字体适配方案原理 **

在设计稿中,计算出字体大小相对于基准字体大小(基准字体大小可以选择设计稿宽度,一般为了计算方便,会把设计稿宽度/10得到的值作为基准字体大小)的比值,然后在不同布局宽度下,先得到基准字体大小,再根据上面计算出来的比值,就可以计算出来不同布局宽度下的字体大小,也就是不同布局宽度下等比例缩放字体。

利用rem的特性,在页面的html标签上设置一个基准字体大小,就可以实现这种方式。

例如,宽是750px的设计图中,字体大小是32px,计算出基准字体大小为75px,比值为 32 * 10 / 75 = 0.426667。

如果布局宽度是414px,此时基准字体大小变成 414 / 10 = 41.4px,然后设置<html style="font-size:41.4px">,字体大小是0.426667rem,计算出来的字体大小为41.4x0.42667=17.66px。

如果布局宽度变成360px,此时基准字体大小变成36px,然后设置<html style="font-size:36px">,字体大小仍然用0.426667rem表示,计算出来的字体大小为36x0.42667=15.36px。

750/32 约等于 414/17.66 约等于 360/15.36,这样就做到了等比缩放字体了。

** 第2种字体适配方案优缺点**

缺点:1.小尺寸设备屏幕上字体显示小,大尺寸设备屏幕字体显示大,导致字体显示不一致;2.不能发挥大屏手机的优势(显示更多的字);3.字体大小会出现奇数或者小数点大小的值,某些字体不支持这些值,渲染时增加计算量;

优点:1.适配简单,不同设备不会影响页面布局,可以和设计稿布局保持一致;

2.3布局宽度适配

布局中对宽度的适配,也是采用rem来实现,和上面第2种字体大小适配方式中的原理类似,也是计算出一个比例值,然后不同布局宽度中等比缩放,这里偷下懒,不在赘述。

3.适配解决方案分析

目前的解决方案有两类

第一类就是js动态生成viewport标签,标签中的initial-scale值根据设备的dpr计算,不同dpr设备的viewport值不同。

第二类就是js不操作viewport,每个设备都使用理想viewport来布局。

<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>

** 动态viewport解决方案分析 **

这里分析两个动态viewport解决方案:

1.手机淘宝的flexible方案;
2.hotcss方案;

手机淘宝的flexible方案,特点:

1.仅针对iphone生成动态viewport,因为目前iphone的dpr只有1,2,3三种,android的dpr很有多种,不具有一致性;

2.字体大小不用rem做缩放处理,仍然使用px单位,设置不同dpr下对应的字体大小;

3.宽度利用rem等比缩放;

4.允许强制定义dpr;

使用时页面头部需要引入flexible.js.

flexible.js的适配流程分析

hotcss方案,特点:

1.不区分iphone和android,dpr只取三种1,2,3,android的dpr做近似处理;

2.宽度以及字体利用rem等比缩放;

3.允许强制定义dpr;

使用时页面头部需要引入hotcss.js

hotcss.js的适配流程分析

动态viewport方案之所以会称为动态viewport是因为,这个适配过程会根据系统dpr值设置initial-scale属性的大小,大小等于1/dpr。

** 静态viewport解决方案分析 **

利用rem特性,先根据标注图算出各元素相对于设计稿宽度的比值,这个比值就作为rem值,然后页面布局时就用算出的rem值表示,并且在html根元素设置当前布局页面宽度作为基准。更rem值计算具体的解释可以参考这篇文章使用Flexible实现手淘H5页面的终端适配。通过这种方式设置标签元素的宽高,位置以及字体大小,这样利用rem特性就可以在不同手机屏幕上实现等比缩放。

参考资料
https://github.com/amfe/article/issues/17
http://www.cnblogs.com/pigtail/archive/2013/03/15/2961631.html

本文由星彩网app下载发布于前端技术,转载请注明出处:活动端H5页面适配难点切磋,移动端适配

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。