而后给出主观的最佳实践。javascript
赶时间戳这里传送门css
比较无聊干燥的文章,看前请喝水。html
研究样本java
ml.js
一个月前去了css开发者大会,听到了手淘的自适应方案,想起以前一直就想了解ml.js到底干了什么事。回来仔细研究了一下,抱着好奇心一并看了一样类型的网站的方案,深刻学习一下。浏览器
研究结论布局
手淘学习
获取手机dpr(window.devicePixelRatio
),动态生成viewport。测试
换取手机宽度,分红10份,每一份的宽度便是rem的尺寸。字体
根据设计稿尺寸(px
)经过计算,转换成rem
去布局。flex
ps
:海外淘宝并无这样作,而是scale1.0而且图片大概
都是2倍图。
天猫
采用scale=1.0
写死viewport。
flex布局,笃定认为布局尺寸是375 (iPhone6
)
rem 肯定非flex的元素
手机携程
采用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. 为了充分利用屏幕的分辨率,使用符合屏幕的图片。
这一条和设计稿密切想关,要讨论它不能抛开设计稿不谈。
这里先补一下切图课
,若是本身要作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 实在是很是低成本还原的方案,何尝不可。
对于这一点,争议较多,由于若是要作到对应倍图的话,意味着图片都须要作三份。成本过高了。
这里一般有两种作法
图片服务
例如在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
定死尺寸
放弃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碎..,嗯,不说了...)
JS动态计算(常见作法)
根据不一样屏幕宽度计算不一样字号大小。
1. 定基准值,设计稿是750宽度(2倍屏),字体的大小是24px. 2. 计算指定宽度的字体大小。 var fontSize = width / 750 * 24 ;
根据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。
无需计算百分比,在不一样的界面上就会自动计算,并且以该浏览器能够识别的最小单位实现,比本身计算的百分比要精准。
结论
写死initial-scale=1.0
对于实现1px问题
, 问题比较大。与设计师沟通协商
才是最好的解决问题的方法。
写死initial-scale=1.0
对于不一样图片的显示, 采用不一样倍图的话,会有必定压缩,但在可接受范围内。(固然,动态生成scale可以完美呈现...)
布局
若是采用动态生成viewport
方案,就用到rem来还原设计稿(还有rem-px的计算)。成本在效率
上。
若是采用写死initial-scale=1.0
方案,就用flex布局,主要成本在flex兼容性
上,可是实现很是灵活简单。
后记
viewport的scale
的重要性远比我想象的要低不少,我本来觉得这就是自适应。
可是后来发现,其实自适应仍是回到了远古时代的百分比%
,只是如今有更聪明更灵活的方式flex
,将来应该有两个方向去自适应。
一个是拥抱vw,vh。(手淘的ml.js十等分宽度,1rem=10vw
)
一个是更好的使用flex
如今使用后者已经有不少的库能够解决兼容性了,如参考资源最后的一个flex库。
调研的网站并很少,可是百分比仍然是不少人的首选。