Web移动端适配总结

一. 1px边框问题

想必各位无论在面试中,还是工作中,应该遇到过1px边框的问题。不知道也没关系,现在我们就来复习一下(知道的朋友可以跳过去看第二部分了)。 1px边框,顾名思义就是前端画出1px的线,这里的1px,指的是屏幕1px大小。那么屏幕的1px和css中的1px有什么区别呢?每个物理像素(也就是屏幕的1px)是 图像显示的最小单元,css的1px是浏览器渲染的基本单位,在普通屏幕下,1px对应1物理像素,在2倍屏、3倍屏下1px分别对应2物理像素、3物理像素。这就好比实验用的 坐标纸,假如纸上有10小格(相当于10个物理像素),作图时把你自己坐标系的一个单位用1小格表示,那么你最终做的图占整个坐标纸的面积就比较小, 把坐标系的一个单位用10小格表示,可能整个坐标纸只能画出一部分图像,但会保留更多细节。在第2种情况下,同一单位长度的线会是第1种情况下的10倍长。浏览器在高倍屏下 渲染也是如此,在2倍屏下画的是2倍粗的线,3倍屏下画的是3倍粗的线。

二. 不同尺寸的屏幕适配

移动端的屏幕适配,不仅仅需要考虑各种尺寸,还要考虑dpr(屏幕像素比,可以理解为每px用多少物理像素显示),dpr = 2就是2倍屏。同样是宽为350px的设备,普通屏看起来正常,2倍屏看起来线条就很 粗,你可能用一些hack例如transform缩放、制造阴影模拟边框,这些多少存在一些问题,如果需要全局都能画出1px的线呢?我们只要保证让1px始终只占1个物理像素就行了。这里使用meta标签的viewport对全局视图进行缩放。 一般是下面这个样子:

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
复制代码

对于2倍屏设置initial-scale=0.5,对于3倍屏设置initial-scale=0.33,因此,我们还需要在网页渲染前用脚本通过window.devicePixelRatio获取dpr,然后将initial-scale设置为 1/dpr。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" language="zh-cn-hans">
        <script>
            (function(){
                function resetViewPort (){
                    var viewport = document.querySelector('meta[name = viewport]');
                    if(!viewport){
                        viewport = document.createElement("meta");
                        var head = document.querySelector("head");
                        head.insertBefore(viewport,head.firstChild);
                    }
                    var ratio = window.devicePixelRatio||1;
                    var content = 'width=device-width,initial-scale='+ Math.round(100/ratio) / 100 +',maximum-scale=1,user-scalable=no';
                    viewport.setAttribute("content",content);
                };
                window.addEventListener('DOMContentLoaded',resetViewPort);
            })()
        </script>
    </head>
    <body>
    </body>
</html>
复制代码

至此,所有屏幕下1px都对应1物理像素了,现在我们只需要考虑不同的屏幕尺寸。不过现在问题来了,因为px的长度已经和之前不一样了,如果现在还用px描述元素,肯定会变小,因此我们需要 用另一种单位来表示元素。现在让我们想想css除了px外还有那些单位?

  • %

  • em,rem

  • vw

  • ...

%一般是相对于父级元素,当有多级嵌套时,就很复杂,不好确定了,同理,em也有这个缺点。再来看rem,它总是相对于根元素的font-size,根元素是唯一的,只要我们保证不同屏幕下根 元素的font-size与屏幕的宽度比例一致,就能得到一样的显示效果。这是个很好的方法,只需要在上面的脚本加几行代码就行了,浏览器兼容性也很好,很多文章也介绍了这种方案。不过今天,他不是我们的主角。再来看看vw,1vw表示的是1/100的屏幕宽度,一个宽为30vw的元素在A设备占屏幕宽度的30%,在B设备同样占屏幕宽度的30%,这不就是我们想要的吗?让我们来看看vw的 兼容性,可以看出vw几乎完全兼容。实际上font-size + rem就是模拟的vw,为何我们不直接用它呢?

三. 自动转换插件

我们一般是拿着设计稿,根据标注写尺寸。标注一般是px为单位,现在写成以vw为单位,则需要进行一个转换。这种换算的工作我们让插件来做,不过目前好像没找到相关postcss插件,于是自己写了一个——postcss-unify,代码很简单只有20行,就是用正则匹配然后替换,感兴趣的你也可以自己做一个。这里简单说一下postcss,它能将css转化为js对象便于我们 操作,再将结果转化成css代码,在这里了解更多(写插件的方法在链接里也有)。

四. 其他

双十一都过了,老子还是单身!
本文参考了很多文章,同时结合了实践探索,有什么不对或更好的地方欢迎提出。
~~都被你看个精光了,还不给个赞?

猜你喜欢

转载自juejin.im/post/5bebc465e51d457c1c4e07ae