http://www.w3ctech.com/topic/979
利用 rem 布局 依照某特定宽度设定 rem 值(即 html 的 font-size),页面任何需要弹性适配的元素,尺寸均换算为 rem 进行布局;当页面渲染时,根据页面有效宽度进行计算,调整 rem 的大小,动态缩放以达到适配的效果。利用该方案,还可以根据 devicePixelRatio 设定 initial-scale 来放大 viewport,使页面按照物理像素渲染,提升清晰度。
优点:
清晰度高,能达到物理像素的清晰度。
能解决 DPR 引起的“1像素”问题。
向后兼容较好,即便屏幕宽度增加、PPI 增加该方案依旧适用。
缺点:
适配 js 需尽可能早进入,减少(避免)viewport 变化引起的重绘。
某些Android机会丢掉 rem 小数部分。
需要预编译库进行单位转换。
开发时,css 及 js 都以 16px 作为基数换算 rem,借助预编译库(以 scss 为例),我们设定一个动态尺寸单位 $ppr: 750px/16px/1rem
,即 pixel per rem,任何使用弹性尺寸的地方写作:width: 100px/$ppr
。
动态调整 rem 的方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var fixScreen = function ( ) { var metaEl = doc.querySelector('meta[name="viewport"]' ), metaCtt = metaEl ? metaEl.content : '' , matchScale = metaCtt.match(/initial\-scale=([\d\.]+)/ ), matchWidth = metaCtt.match(/width=([^,\s]+)/ ); if ( !metaEl ) { var docEl = doc.documentElement, maxwidth = docEl.dataset.mw || 750 , dpr = isIos ? Math .min(win.devicePixelRatio, 3 ) : 1 , scale = 1 / dpr, tid; docEl.removeAttribute('data-mw' ); docEl.dataset.dpr = dpr; metaEl = doc.createElement('meta' ); metaEl.name = 'viewport' ; metaEl.content = 'initial-scale=' + ratio + ',maximum-scale=' + ratio + ', minimum-scale=' + scale; docEl.firstElementChild.appendChild(metaEl); var refreshRem = function ( ) { var width = docEl.getBoundingClientRect().width; if (width / dpr > maxwidth) { width = maxwidth * dpr; } var rem = width / 16 ; docEl.style.fontSize = rem + 'px' ; }; refreshRem(); } }
代码实现主要参考淘宝网触屏版 的适配方法,查看效果和代码 ,其中 scss 的写法可以参见这里 。
注意,较小的背景图(比如一些 icon)的 background-size 不要使用具体 rem 数值,裁剪后会出现边缘丢失。应使用与元素等尺寸切图,设定 background-size: contain|cover 来缩放。