本文属于原创文章,转载请注明--来自桃源小盼聊技术javascript
关于flexible的第一篇介绍文章是大漠
的《使用Flexible实现手淘H5页面的终端适配》。请先阅读这篇文章再来看本文。css
三年前看的时候就一个感受Perfect
,还有这么神奇的操做,可是深刻到原理就有点似懂非懂,向其余同窗推荐的时候,总有些细节讲不清楚。究其缘由是本身没有深刻了解“为何会产生这样的解决方案?”。html
这种方案受到vw
这个单位的启发,100vw等于设备宽度,跟具体像素无关,有点相似100%。但百分比没法解决宽高比的问题。html5
rem单位是参照根节点的font-size为依据,因此只要根据设备宽度来除以100份,动态计算根节点的字体大小,就能hack这个vw的效果。java
1vw = (ClietWidth/100)= htmlFontSize = 1rem
复制代码
flexible将页面分红了10份,为何不像vw单位同样是100份呢?拿iPhone4举例,宽度为320px,若是是100份,1rem=3.2px,目前大部分浏览器不支持12px如下的字体大小,因此320/12=26.67,最多能够将页面分红26份,方便计算取整数10,1rem=(320/10)=32px。android
先看一下设备的实际像素与css像素的统计图。浏览器
在iphone4以前没有视网膜屏幕,一个设备像素等于一个css像素。最开始的移动端网站大可能是按照240px或320px的设计图开发,iphone3GS就是320px,那么在iPhone4的640px上,整个网站只能显示一半,看起来很奇怪。就算厂商会自动缩放整个网站来适配 屏幕,也没法解决固定像素的问题。app
考虑到这方面的影响,iPhone4的物理像素比(devicePixelRatio)dpr=2,将一个像素的宽度和高度都扩大二倍,手机在底层对网站进行了显示上的放大,这样一来屏幕对于原有的网站仍是320px。iphone
这是计算rem的关键代码字体
var docEl = document.documentElement
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
复制代码
clientWidth
是根元素的可视宽度,若是viewport缩放scale=1.0,那么对于iPhone4的clientWidth=320px,若是scale=0.5,那么clientWidth=640px,不管如何改变viewport值,rem都等于根节点可视宽度的1/10。
老版本0.3.2
里有这样一段。
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其他的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其余设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
复制代码
动态去计算scale,并不影响rem的计算,好处是解决了1px的问题,坏处是破坏了css媒介media。 老版本对android不支持高清方案,是个缺陷。
新版本2.0
里面则去掉了动态计算scale的方式,改成检测是否支持0.5px的特性,经过添加类名hairlines
来向下兼容
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
复制代码
css里的1rem=clientWidth/10,效果图与设备像素计算的共同关联是都把屏幕分红10份,那么iphone4效果图里的1rem=(640/10)=64px。 因此css的转化基础永远是width/10。
这篇文章主要是记录思考为何这样作的解答。但愿有更多的疑问来让咱们一块儿思考。
现在淘宝家也升级了适配方案,拥抱真正的vw。参考大漠后来的文章《再聊移动端页面的适配》