刚进部门就被拉去趟移动端Web的浑水,拿到视觉稿的时候,一看,恩不错,小清新。然后就开始一个像素一个像素的量,十分满意自己的成果。然后手机扫一扫一看,我了个擦,字体怎么这么大!!!间距怎么这么大!!!还跑去问视觉姐姐为什么这么大。。视觉姐姐一脸无奈的说我这个是按照640的宽度设计的。我突然意识到移动端屏幕碎片化巨大,而且还有什么Retina屏幕,我奥了一声就囧囧的退下了。。。
当然想到的第一方法就是问前辈了,问他们之前怎么做的,前辈说直接按视觉稿来,我说640太大了,他说除以2啊,按320来。。我说不行吧,屏幕多种多样的,6 plus显示的得多小。。他说你和视觉沟通下。。。orz。。。
还是自食其力吧——网络搜索,大概能搜到一些,不过要么太高大全(淘宝的方案),要么都是零零碎碎的。最终根据淘宝的方案还有Rem这个单位,自己做了一套简单的方案。
开始呢,还是要对一些概念做一些说明,当然不是我说明。。。
最终的目的就是知道:
设备像素比 = 物理像素 / 设备独立像素
window.devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例。
公式表示就是:window.devicePixelRatio = 物理像素 / dips
淘宝的方案
首先使用JavaScript动态计算dpr,就是上面我们说道的设备像素比,然后在html head里设置viewport里的width以及scale,使得屏幕整体缩放,比较完美的解决了border 1px、各种奇葩屏幕的适配问题。并且在html上加一个自定义的属性data-dpr来针对不同的屏幕写css。
/** * 动态计算dpr */ var dpr, rem, scale; var docEl = document.documentElement; var fontEl = document.createElement(‘style‘); var metaEl = document.querySelector(‘meta[name="viewport"]‘); dpr = window.devicePixelRatio || 1; rem = docEl.clientWidth * 2 / 10; scale = 1 / dpr; // 设置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;
然后对于div、字体或者其他css属性,都使用data-dpr来做媒体查询写不同的css。
个人感脚,有种太高大全的感觉,而且有些复杂了。最最重要的,有的手机,比如我的千元智能机,没有识别meta标签的缩放,页面依然巨大。
媒体查询
我感觉最经济实惠的就是媒体查询了,根据市场占有率与自己产品所注重的用户群体,得出需要适配的机型和屏幕,写media query即可了。
@media (min-device-width : 375px) and (max-device-width : 667px) and (-webkit-min-device-pixel-ratio : 2){ /*iphone 6*/ } @media (min-device-width : 414px) and (max-device-width : 736px) and (-webkit-min-device-pixel-ratio : 3){ /*iphone 6 plus*/ }
给出NEC的方案:
/* media */ /* 横屏 */ @media screen and (orientation:landscape){ } /* 竖屏 */ @media screen and (orientation:portrait){ } /* 窗口宽度<960,设计宽度=768 */ @media screen and (max-width:959px){ } /* 窗口宽度<768,设计宽度=640 */ @media screen and (max-width:767px){ } /* 窗口宽度<640,设计宽度=480 */ @media screen and (max-width:639px){ } /* 窗口宽度<480,设计宽度=320 */ @media screen and (max-width:479px){ } /* windows UI 贴靠 */ @media screen and (-ms-view-state:snapped){ } /* 打印 */ @media print{ }
弱弱的拿出我的方案
我的方案,借鉴了淘宝的JavaScript脚本,动态的设置html的font-size,其余的css属性使用rem设置。
那么需要确定的font-size的基准值,一般设计稿都是640px宽度给出的,还有一些更高清的750px的,这里借鉴了这篇文章,640px宽度时将基准值设置为20px。
然后在每个html页面的head加入JavaScript代码:
(function(window) { var dpr, rem; var docEl = document.documentElement, fontEl = document.createElement(‘style‘); dpr = window.devicePixelRatio || 1; rem = docEl.clientWidth / 320 / 2 * 20; // 以640px,html font-size 20px为基准. docEl.setAttribute(‘data-dpr‘, dpr); docEl.firstElementChild.appendChild(fontEl); fontEl.innerHTML = ‘html{font-size: ‘ + rem + ‘px!important;}‘; //备用 window.rem2px = function(v) { return parseFloat(v) * 20; } window.px2rem = function(v) { return parseFloat(v) / 20; } window.dpr = dpr; window.rem = rem; })(window);
这样,简单的适配了几乎所有的屏幕,用在自己的项目里,效果还不错。
其他问题
border 1px
除了淘宝的粗暴的缩放,其余的方式都是合适的时候用合适的方法。
我比较喜欢scale的方式。
.scale{ position: relative; } .scale:after{ content:""; position: absolute; bottom:0px; left:0px; right:0px; border-bottom:1px solid #ddd; -webkit-transform:scaleY(.5); transform:scaleY(.5); -webkit-transform-origin:0 0; transform-origin:0 0; }
需要判断是不是高清屏,要不缩放了就不显示了。
if(window.devicePixelRatio >= 2){ document.querySelector(‘xxxx‘).classList.add(‘scale‘); }
也可以使用media query。
高清图片
我觉得,这个最好有专门的工具做,比如网易的NOS,可以对图片做不同的处理,根据参数返回不同质量的图片。
总结
刚刚接触,查询了一些资料,链接基本都在文章里了。一定还有需要完善的地方或者更好的方式,欢迎一起讨论。