移动端自适应方案(转载)

  • 真的须要动态生成viewport吗?
  • 如何自适应?

而后给出主观的最佳实践。javascript

  • 最帅的flex

赶时间戳这里传送门css

比较无聊干燥的文章,看前请喝水。html

研究样本java

  1. 手淘 ml.js
  2. 天猫首页
  3. 手机携程

一个月前去了css开发者大会,听到了手淘的自适应方案,想起以前一直就想了解ml.js到底干了什么事。回来仔细研究了一下,抱着好奇心一并看了一样类型的网站的方案,深刻学习一下。浏览器

研究结论布局

  1. 手淘学习

    • 获取手机dpr(window.devicePixelRatio),动态生成viewport。测试

    • 换取手机宽度,分红10份,每一份的宽度便是rem的尺寸。字体

    • 根据设计稿尺寸(px)经过计算,转换成rem去布局。flex

    ps:海外淘宝并无这样作,而是scale1.0而且图片大概都是2倍图。

  2. 天猫

    • 采用scale=1.0 写死viewport。

    • flex布局,笃定认为布局尺寸是375 (iPhone6)

    • rem 肯定非flex的元素

  3. 手机携程

    • 采用scale=1.0 写死viewport

    • px + 百分比布局

实现以前

说起实现以前,先简单过一些概念。

完美视口

完美视口的概念已经街知巷闻了,若是不知道能够先戳这里。

在这几篇文章里,还会学会设备像素,css像素等概念,大神讲的很透彻,这里就不献丑了。

ppk 谈 viewport其1 ppk 谈 viewport其2 ppk 谈 viewport其3

这里给出完美视口

<meta name="viewport" content="initial-scale=1.0,width=device-width,user-scalable=0,maximum-scale=1.0"/> 

在移动端,低端无定制的需求,均可以用这个完美视口完成。然而看到这篇文章的你,显然完美视口还不能知足。

dpr

dpr是devicePixelRatio的简写,也就是屏幕分辩比

历史缘由,因为苹果retina的产生,使得清晰度提高,主要是由于`设备像素`提高了一倍,所以能够用更多像素去绘画更清晰的图像。#我乱说的#

坊间对于dpr更通俗的说法叫

  • 一倍屏
  • 两倍屏
  • 三倍屏

scale

scale是屏幕拉伸比。也就是视口上的initial-scale , maximum-sacle 等属性。

scale 和 dpr的关系是倒数。

直观感觉

这是我对dpr的直观感觉

一样去展现 1 x 1 像素的点,虽然在屏幕上看到的大小是同样,但背后表现它的像素数量是不一样。

这也意味着,在同样大小的面积内,更多物理像素的屏幕上展示色彩的能力越强。

但这不是我要关注的点,咱们关注的是。

1. 是否须要根据倍屏去切换scale达到伸缩的目的

2. 切换scale的成本和回报

下面根据几个实验来回答这两个问题。

自适应问题

实验1 - 传说中的1px

大多数给出要动态切换scale的理由有如下两个。

1. 1px并非 [ 真实的1px ] , 2. 为了充分利用屏幕的分辨率,使用符合屏幕的图片。 

真实的1px

这一条和设计稿密切想关,要讨论它不能抛开设计稿不谈。

这里先补一下切图课,若是本身要作1x , 2x, 3x 的设计稿。如何去实现?

尺寸!!!

大多数状况下,设计师产出各类尺寸的稿子(事实上通常只是2倍稿子),都是先画出大尺寸的稿子,再去缩小尺寸,最后导出。 这样会带来问题:

若是设计师在2倍稿子里画了一条1px的线,这时候假如咱们要在scale=1.0里呈现的话,就会变成0.5px,以下图。

而很大一部分手机是没法画出0.5px的,所以这里通常有一个hack

transform:scaleX(0.5)或transform:scaleY(0.5) 

可是有人提出了, 既然能够改变viewport的scale达到合理利用不一样倍屏的优点,为何不这么写呢。

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

等等,为了设计稿的尺寸咱们如此大费周章?

 

事实上,即便2x设计稿避免了1px。3x设计稿也可能出现2px。

并且这里若是写死scale可能形成部分地方和稿子出入较大,没法还原设计稿,界面的显示会打折扣。

解决这个问题的关键在于:交流

  • 若是你的设计师是个要求严格,并且产品界面把控很是严格的话,应该动态去实现viewport或使用scale的hack去改变。

  • 若是部分区域实在没有必要[ 过分优化 ], scale=1.0 实在是很是低成本还原的方案,何尝不可。

对应倍图

对于这一点,争议较多,由于若是要作到对应倍图的话,意味着图片都须要作三份。成本过高了。

这里一般有两种作法

  1. 图片服务

    例如在100x100的图片容器中。

    1倍图 http:// img.xxx.com/abc.jpg_100x100 2倍图 http:// img.xxx.com/abc.jpg_200x200 3倍图 http:// img.xxx.com/abc.jpg_300x300 
  2. 定死尺寸

    放弃1屏手机,所有启用2倍图,因为流量会消耗比较大(低端机),所以滚动加载等优化手段就会显得比较重要了。

实验1 - scale对倍图重要吗

这里看一下不一样scale下图片的差别。

  • 测试样本:160x160凯尔特人队标logo(一不当心暴露了绿色的血液)

  • 测试容器:160x160 img标签

  • 测试环境: intial-scale分别为1.0 / 0.5 / 0.3333

  • 图片尺寸: 1x(160x160) 2x(320x320) 3x(480x480)

    测试结论:不一样scale下使用不一样图片差别很是大。

    可是这里须要验证,是否不一样scale同一图片差别起到绝对做用。

    肉眼观看基本无区别,除了用取色器去获取,会发现有色差和部分像素被分割(下面会说到),以外,用不一样scale显示同一图片基本没有什么区别。

实验2 - DownSampling

因为上一个实验最后的图片,使用同一scale下,不一样倍数的图片,存在色差,这里验证一下。

  • 测试方案

    测试图片:

    图片尺寸: 400x300 , 300x225 , 200x150 , 100x75

    测试环境: scale = 1.0

    测试容器: 100x75的 img元素

    因为以前知道了DownSampling概念的存在,这里只是好奇心驱动试验一下。(对自适应其实没有卵用)

    DownSampling是说大图放入比图片尺寸小的容器中的时候,出现像素分割成就近色的状况。

     

    测试结果:

    注:6plus貌似和其余机型不一样。

    触发状况: 不一样颜色像素接触的地方,会出现DownSampling。

rem

对于rem要说的很少,看这张图。对于用到px的元素,使用rem统一去管理是很灵活的!(这里原谅我盗图了..)

字体

不管是采用动态生成viewport或者写死scale,字体都须要适配大屏。以前提出的rem方案被证明在不一样手机上显示不一致,这里仍是回归成了px。

px最好用双数

 

两种方案(这里不考虑媒体查询,由于Android碎..,嗯,不说了...)

  1. JS动态计算(常见作法)

    根据不一样屏幕宽度计算不一样字号大小。
    
    
    1. 定基准值,设计稿是750宽度(2倍屏),字体的大小是24px. 2. 计算指定宽度的字体大小。 var fontSize = width / 750 * 24 ; 
  2. 根据dpr设定 (比较好的作法)

    ps : 通常时初始化时设置为根元素html的attribute,

    window.document.documentElement.setAttribute('dpr',window.devicePixelRatio) 

    而后css这样写

    [dpr=1] { font-size=16px; } [dpr=2] { font-size=32px; } 

布局

权衡之下,我以为flex真的灵活方便太多,所以这里给出一个布局demo。大体以下图。(画的比较粗糙..)

(左稿右还原)

基本涵盖:

  • 固定头部
  • 固定底部
  • 多列自适应
  • 高度自定义
  • 内容滚动

为何flex可以作到百分比作不到的自适应。

好比咱们也去学天猫,笃定认为宽度就是375(iPhone6尺寸),那么两个元素flex分别为200和175。

无需计算百分比,在不一样的界面上就会自动计算,并且以该浏览器能够识别的最小单位实现,比本身计算的百分比要精准。

demo传送门

结论

  1. 写死initial-scale=1.0 对于实现1px问题, 问题比较大。与设计师沟通协商才是最好的解决问题的方法。

  2. 写死initial-scale=1.0 对于不一样图片的显示, 采用不一样倍图的话,会有必定压缩,但在可接受范围内。(固然,动态生成scale可以完美呈现...)

  3. 布局

    若是采用动态生成viewport方案,就用到rem来还原设计稿(还有rem-px的计算)。成本在效率上。

    若是采用写死initial-scale=1.0方案,就用flex布局,主要成本在flex兼容性上,可是实现很是灵活简单。

后记

viewport的scale的重要性远比我想象的要低不少,我本来觉得这就是自适应。

可是后来发现,其实自适应仍是回到了远古时代的百分比%,只是如今有更聪明更灵活的方式flex,将来应该有两个方向去自适应。

  • 一个是拥抱vw,vh。(手淘的ml.js十等分宽度,1rem=10vw

  • 一个是更好的使用flex

如今使用后者已经有不少的库能够解决兼容性了,如参考资源最后的一个flex库。

调研的网站并很少,可是百分比仍然是不少人的首选。

相关文章
相关标签/搜索