缺点:通过设备宽度范围区间这样的媒体查询来动态改变rem基准值,其实不够精确,比如:宽度为360px 和 宽度为320px的手机,因为屏宽在同一范围区间内(<375px),所以会被同等对待(rem基准值相同),而事实上他们的屏幕宽度并不相等,它们的布局也应该有所不同。最终,结论就是:这样的做法,没有做到足够的精确,但是够用。
javascript方式,通过上面的公式,计算出基准值rem,然后写入样式,大概如下(代码参考自kimi的m-base模块)
var dpr, rem, scale; var docEl = document.documentElement; var fontEl = document.createElement('style'); var metaEl = document.querySelector('meta[name="viewport"]'); scale = 1 / dpr; dpr = win.devicePixelRatio || 1; rem = docEl.clientWidth * dpr / 10; // 设置viewport,进行缩放,达到高清效果 metaEl.setAttribute('content', 'width=' + dpr * docEl.clientWidth + ', initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no'); // 设置data-dpr属性,留作的css hack之用 docEl.setAttribute('data-dpr', dpr); // 动态写入样式 docEl.firstElementChild.appendChild(fontEl); fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}'; // 给js调用的,某一dpr下rem和px之间的转换函数 window.rem2px = function(v) { v = parseFloat(v); return v * rem; }; window.px2rem: function(v) { v = parseFloat(v); return v / rem; }; window.dpr = dpr; window.rem = rem;这种方式,可以精确地算出不同屏幕所应有的rem基准值,缺点就是要加载这么一段js代码,但个人觉得是这是目前最好的方案了。
因为这个方案同时解决了三个问题:
1)border: 1px问题
2)图片高清问题
3)屏幕适配布局问题
说到布局,自然就得回答一下最初的留下的那个问题:如何在css编码中还原视觉稿的真实宽高?
前提条件:
1)拿到的是一个针对iPhone6的高清视觉稿 750×1334
2)采用上述的高清方案(js代码)。
如果有一个区块,在psd文件中量出:宽高750×300px的div,那么如何转换成rem单位呢?
公式如下:
rem = px / 基准值;
对于一个iPhone6的视觉稿,它的基准值就是75(之前有提到);
所以,在确定了视觉稿(即确定了基准值)后,通常我们会用less写一个mixin,像这样:
// 例如: .px2rem(height, 80); .px2rem(@name, @px){ @{name}: @px / 75 * 1rem; }所以,对于宽高750×300px的div,我们用less就这样写:
.px2rem(width, 750); .px2rem(height, 300);转换成html,就是这样:
width: 10rem; // -> 750px height: 4rem; // -> 300px最后因为dpr为2,页面scale了0.5,所以在手机屏幕上显示的真实宽高应该是375×150px,就刚刚好。
倘若页面并没有scale 0.5,我们的代码就得这样:
.px2rem(width, 375); .px2rem(height, 150);这样的宽高,我们往往是这样得来的:
1)将750×1334的视觉稿转成375×667的大小后,再去量这个区块的大小(感觉好傻)。
2)在750×1334量得区块宽高是750×300px后,再口算除以2(感觉好麻烦)。
最后给出一张没有布局适配(上图)和用rem布局适配(下图)的对比图:
(上面的手机分别是:iPhone3gs, iPhone5, iPhone6)
很明显可以看出,rem适配的各个区块的宽高都会随着手机屏宽而改变,最最明显的可以看一下图片列表那部分,最后一张图视觉稿要求只出现一点点,rem布局在任何屏幕下都显示的很好。
字体大小问题
既然上面的方案会使得页面缩放(scale),对于页面区块的宽高,我们可以依赖高清视觉稿,因为视觉稿本来就×2了,我们直接量就可以了,那么对于字体该如何处理呢?
对于字体缩放问题,设计师原本的要求是这样的:任何手机屏幕上字体大小都要统一,所以我们针对不同的分辨率(dpr不同),会做如下处理:
font-size: 16px; [data-dpr="2"] input { font-size: 32px; }(注意,字体不可以用rem,误差太大了,且不能满足任何屏幕下字体大小相同)
为了方便,我们也会用less写一个mixin:
.px2px(@name, @px){ @{name}: round(@px / 2) * 1px; [data-dpr="2"] & { @{name}: @px * 1px; } // for mx3 [data-dpr="2.5"] & { @{name}: round(@px * 2.5 / 2) * 1px; } // for 小米note [data-dpr="2.75"] & { @{name}: round(@px * 2.75 / 2) * 1px; } [data-dpr="3"] & { @{name}: round(@px / 2 * 3) * 1px } // for 三星note4 [data-dpr="4"] & { @{name}: @px * 2px; } }(注意:html的data-dpr属性就是之前js方案里面有提到的,这里就有用处了)
根据经验和测试,还是会出现这些奇奇葩葩的dpr,这里做了统一兼容~
用的时候,就像这样:
.px2px(font-size, 32);当然对于其他css属性,如果也要求不同dpr下都保持一致的话,也可以这样操作,如:
.px2px(padding, 20); .px2px(right, 8);最后
上面对移动端H5高清和多屏适配的一些方案总结,和知识讲解,不对的地方,还请指出来。
转自