谈一谈麻烦的移动端适配

经过几天的折腾,对移动端适配有了比较全面的了解,移动端适配需要解决的主要问题在于:

1、终端适配

2、retina高清屏幕带来的显示差异

本来想自己总结,但真的还差点火候,需要进一步的实践,所以转载一篇比较全面的文章,文章从物理像素、逻辑像素开始讲起、掠过viewport,直击移动端适配的痛点,最后,将retina屏幕的1px问题、以及适配方案归纳整理。附带源码,详细全面。因担心这么好的文章会消失掉,所以还是转到自己的博客比较好。

原文地址如下https://juejin.im/post/5bbb014ee51d450e452ae015,感谢博主‘梦想攻城狮‘的分享。

物理像素、逻辑像素

  • 物理像素(设备像素):显示设备中一个最微小的物理部件。屏幕这块物理材料上横向和纵向共有多少个像素点,任何设备屏幕的物理像素出厂时就确定了,且固定不变
  • 逻辑像素(设备独立像素):程序使用的虚拟像素(比如说CSS像素),程序认为横向和纵向有多少个像素点,然后由相关系统转换为物理像素
 iPhone5iPhone6iPhone8Plus
逻辑像素568x320667x375736x414
物理像素1136x6401334x7502208x1242

高清屏和像素比

像素点

图片是由很多的像素点构成,每个像素点显示的色彩不一样,构成了一副图片。你可以想象把蒙娜丽莎放大很多倍,然后裁成大小相同的小块,然后拼在一起,这个就是像素点

高清屏

同样大小的圆,里面容纳的正多边形的边数越多,其形状越接近圆,面积越接近圆。类似相同尺寸的屏幕,一个电容点所容纳的像素点越多,一个点可以由更多的像素点搭配来成像则效果当然更细腻,屏幕显得更清晰。

像素比

设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系,它决定了一个点是由多少个像素点来描绘。所以在开发的时候才会有@1、@2和@3图片区别。

 iPhone5iPhone6iPhone8Plus
逻辑像素568x320667x375736x414
物理像素1136x6401334x7502208x1242
屏幕倍率@2@2@3
dpr223

视口viewport

  • 布局视口(layout):在html中一般在meta中的name为viewport字段就是控制的布局视口。布局视口一般都是浏览器厂商给的一个值,移动端在不设置的情况下为980px。
document.documentElement.clientWidth(clientHeight) // 布局视口的尺寸。
复制代码
  • 视觉视口(visiual):浏览器可视区域的大小,即用户看到的网页的区域。(其宽度继承的layout宽度)
window.innerWidth(innerHeight)  // 视觉视口尺寸
复制代码
  • 理想视口(ideal):layout-viewport = width.screen.width(逻辑像素横向)。
<meta name="viewport" content="width=device-width">
复制代码

由于以前的PC页面尺寸比较小,手机在没有进行viewport设置时默认的时980px,可以兼容大多数情况,部分页面页面显示太小,部分页面显示不下而出现滚动条。所以为了达到理想视口,将layout-viewport设置和手机逻辑像素一样大小。但是由于高清屏,设计稿一般和手机物理像素一致,如果设置layout-viewport为逻辑像素,手机程序只会用逻辑尺寸长度去布局,那么横向只能显示正常设计稿的1/2或1/3,就会出现滚动条。

1px问题

在理想视口的情况下,layout-viewport的尺寸大小是逻辑尺寸大小,所以CSS中的1px就是逻辑尺寸的1px,在显示的时候,手机会根据dpr对其进行转化,导致CSS中的1px其实对应的两倍屏2px,三倍屏的3px,所以导致1px的线在这种情况下会变粗。

  1. IOS解决方案
.border { border: 1px solid #999 }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
    .border { border: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
    .border { border: 0.333333px solid #999 }
}
复制代码
  1. :before, :after与transform(兼容)
.radius-border{
    position: relative;
}
@media screen and (-webkit-min-device-pixel-ratio: 2){
    .radius-border:before{
        content: "";
        pointer-events: none; /* 防止点击触发 */
        box-sizing: border-box;
        position: absolute;
        width: 200%;
        height: 200%;
        left: 0;
        top: 0;
        border-radius: 8px;
        border:1px solid #999;
        -webkit-transform(scale(0.5));
        -webkit-transform-origin: 0 0;
        transform(scale(0.5));
        transform-origin: 0 0;
    }
}
复制代码
  1. viewport缩放
//dpr为2时,安卓下通过flexible.js动态设置无效,initial-scale=0.5始终默认为1
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
复制代码

适配方案

从1px的适配中,可以知道viewport缩放是为了消除高清屏倍率的影响。所以一般适配主要从两方面着手:

  • 利用viewport进行缩放来消除高清屏倍率的问题
  • 利用rem来消除高清屏倍率的问题
  • 利用rem调整不同设备之间的逻辑尺寸不一致的问题

固定viewport为理想视口

  1. 固定高度,宽度自适应:
<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
复制代码

垂直方向使用固定的值,水平方向使用弹性布局,元素采用定值、百分比、flex布局等。这种方案相对简单,还原设计稿程度较低,尺寸一般都采用百分比和固定值,不能跟随设备变化而调整,高清屏的设计稿尺寸要缩小1/2或1/3。

  1. 根据不同屏幕动态写入font-size,以rem作为宽度单位。
var width = document.documentElement.clientWidth;   // 屏幕的布局视口宽度
var rem = width / 7.5;  //750px设计稿将布局视口分为7.5份 
rem = px * 0.01;    //1rem等于设计稿上的100px

在ipone6上: 
width = document.documentElement.clientWidth = 375px;
rem = 375px / 7.5 = 50px; 
0.75rem = 37.5px; (37.5/375=10%;占屏幕10%) 
在任意其他机型上:
width = document.documentElement.clientWidth = 420px;
rem = (375px / 7.5)*(420/375) = 420/7.5 = 56px; 
0.75rem = 42px = (420/375)*37.5px 
复制代码

利用rem来消除高清屏倍率的问题,利用rem调整不同设备之间的逻辑尺寸不一致的问题,利用百分比还原设计图,但是无法消除1px的影响

动态设置viewport

  1. 根据不同屏幕动态写入font-size和viewport,以rem作为宽度单位。
var width = document.documentElement.clientWidth;   // 屏幕的布局视口宽度
var rem = width / 10;                               // 将布局视口分为10份

var devicePixelRatio = window.devicePixelRatio;
var isIPhone = window.navigator.appVersion.match(/iphone/gi);
var dpr,scale; 
if (isIPhone) { 
    if (devicePixelRatio >=3) { 
    dpr = 3; 
    } else if (devicePixelRatio >=2) { 
    dpr = 2; 
    } else { 
    dpr = 1; 
    } 
} else { 
    dpr = 1; 
} 
scale = 1 / dpr; 

在ipone6上: 
width = document.documentElement.clientWidth = 750px;
rem = 750px / 10 = 75px; 
1rem = 75px; 
在任意其他机型上:
width = document.documentElement.clientWidth = 840px;
rem = (840px / 10)*(420/375) = 420/7.5 = 94.08px; 
1rem = 94.08px = (420/375)*75px   
复制代码

利用viewport进行缩放来消除高清屏倍率的问题,能消除1px的问题,利用rem调整不同设备之间的逻辑尺寸不一致的问题,利用百分比还原设计图,但是其1rem等于75px或者其他不固定尺寸不方便计算。

  1. vw和viewport放缩
var devicePixelRatio = window.devicePixelRatio;
var isIPhone = window.navigator.appVersion.match(/iphone/gi);
var dpr,scale; 
if (isIPhone) { 
    if (devicePixelRatio >=3) { 
    dpr = 3; 
    } else if (devicePixelRatio >=2) { 
    dpr = 2; 
    } else { 
    dpr = 1; 
    } 
} else { 
    dpr = 1; 
} 
scale = 1 / dpr; 

100vw = 100%width 
复制代码

这种方式类似于rem = 750px / 10 的方案,只不过用vw来替代了rem,但是它有一个好处就是将rem解放出来,所以rem用来设置字体的大小,在移动端可以兼容用户设置字体大小的影响。

  1. 根据不同屏幕动态写入font-size和viewport,以rem作为宽度单位。为了消除这种不利的影响将上面进行修改:
var width = document.documentElement.clientWidth;   // 屏幕的布局视口宽度
var rem = width / 7.5;  //750px设计稿将布局视口分为7.5份 
rem = px * 0.01;    //1rem等于设计稿上的100px

var devicePixelRatio = window.devicePixelRatio;
var isIPhone = window.navigator.appVersion.match(/iphone/gi);
var dpr,scale; 
if (isIPhone) { 
    if (devicePixelRatio >=3) { 
    dpr = 3; 
    } else if (devicePixelRatio >=2) { 
    dpr = 2; 
    } else { 
    dpr = 1; 
    } 
} else { 
    dpr = 1; 
} 
scale = 1 / dpr; 

在ipone6上: 
width = document.documentElement.clientWidth = 750px;
rem = 750px / 7.5 = 100px; 
0.75rem = 75px; 
在任意其他机型上:
width = document.documentElement.clientWidth = 840px;
rem = (750px / 7.5)*(840/750) = 840/7.5 = 56px; 
0.75rem = 84px = (840/750)*75px 
复制代码

利用viewport进行缩放来消除高清屏倍率的问题,能消除1px的问题,利用rem调整不同设备之间的逻辑尺寸不一致的问题,利用百分比还原设计图,方便计算。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值