面试问到移动端,适配是必问的了,今天在此总结一下
移动端适配解决方案
一、 viewport(scale=1/dpr)
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
各个属性的含义:
device-width等于理想视口的宽度,设置width=device-width就相当于让布局视口等于理想视口。
initial-scale = 理想视口宽度 / 视觉视口宽度,设置initial-scale=1就相当于让视觉视口等于理想视口。
这时,1个CSS像素就等于1个设备独立像素,而且我们也是基于理想视口来进行布局的,所以呈现出来的页面布局在各种设备上都能大致相似。
二、rem
rem是css3新增的一个相对单位。rem为相对HTML根元素的大小,除了IE8及更早的版本外,其他浏览器都支持rem。
阿里早期开源了一个移动端适配解决方案 —— flexible。通过这种方案,我们在页面上统一使用rem布局。
核心代码:
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit();
上面的代码中,将html节点的font-size设置为页面clientWidth(布局视口)的1/10,即1rem就等于页面布局视口的1/10,这就意味着我们后面使用的rem都是按照页面比例来计算的。
这样我们只需要将设计稿的px转成对应的rem即可。
在viewport和vw、vh存在兼容性问题的时候,阿里提出了这种解决方案。但是这种方案实际上是根据屏幕大小百分百还原设计稿,也就是说在屏幕大的设备上看到的元素会大一些,但是这个显然不符合我们的需求。用户使用更大的屏幕并不是为了看到更大的字,而更多地是为了看到更多的内容。
因此,这种方案最后被淘汰掉。
三、vm/vh
vh、vw方案即将视觉视口宽度 window.innerWidth 和视觉视口高度 window.innerHeight 等分为 100 份。
这种方案和上面的方案解决问题的思路一样。这个是需要将设计稿的px转成对应的vw,当然这种比例关系我们不用手动计算,webpack解析css时有个postcss-px-to-viewport插件,可以实现px到vw的自动转化。
这种方案同样存在上面提到的无法看更多内容的问题。另外,px转换成vw不一定能完全整除,因此有一定的像素差。
四、flex
在更大的屏幕上,flex布局可以完美地为用户呈现更多内容。、
移动端适配整体流程
在 head 设置 width=device-width 的 viewport‘
在 css 中使用 px
在适当的场景使用 flex 布局,或者配合 vw 进行自适应
在跨设备类型的时候(pc <-> 手机 <-> 平板)使用媒体查询
在跨设备类型如果交互差异太大的情况,考虑分开项目开发
1px问题及解决方案
1px问题
这里的1像素指的是CSS像素。因此我们可以发现,在写1px的时候,在不同dpr的物理设备上映射的设备像素是不同的。dpr为2时,映射的像素为2px;dpr3时就映射成3px。这样的话,如果在屏幕尺寸比较大的设备上(准确来说时设备像素比较大),1px渲染出来就样子就会有些粗。
解决方案
利用媒体查询 + css3的transform
利用媒体查询区分二倍屏和三倍屏,利用transform:scale(xx)对高度进行缩放。代码如下:
/*二倍屏*/
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
.my-border::after {
transform: scaleY(0.5);
webkit-transform: scaleY(0.5);
}
}
/*三倍屏*/
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
.my-border::after {
transform: scaleY(0.33);
webkit-transform: scaleY(0.33);
}
}
小知识
浏览器默认字体为16px
浏览器最小字号12px
p代表的是纵向的像素数,1080p是指纵向有1080个像素
k代表的是横向的像素数,2k屏是指横向超过2048个像素的屏