为什么要移动端适配

    |     2020年3月22日   |   web前端技术, 移动端   |     0 条评论   |    1117

很多人一听移动端适配就想:直接 px 写死、剩下自适应不就完了?要求严格的团队会要求缩放比例一致,简单说就是每台手机同一行的字数都要一样。下面从像素、分辨率、DPR 讲到 viewport、rem、vw 和推荐的 px + flex 流程。

设计稿常按 375 宽来画,但各品牌物理分辨率不同,逻辑分辨率也不一样。左右布局如果左边写死、右边自适应,右边能展示的内容量就会随设备变,这正是要适配的原因。

一、为什么要适配:像素与分辨率

先看一张总览:

╬в╨┼╜╪═╝_20200322213330

屏幕尺寸按对角线计量,单位英寸。下图两条对角线长度就是屏幕尺寸:

╬в╨┼╜╪═╝_20200322213423

像素

上图 320×480 叫分辨率:横向 320 个像素、纵向 480 个像素。像素(pixel)是组成图像亮度和色度的最小单元,也是软硬件能控制的最小单位。一幅图由成千上万像素紧挨着,人眼看成整图。单位面积像素越多效果越好。每个像素的物理大小不固定,由设备分辨率决定。

分辨率

屏幕分辨率是纵横像素点数,单位 px,决定屏幕能显示多少信息。同样尺寸的屏,640×480 时像素少、单个像素大;1600×1200 时像素多、单个像素小。

奇怪的是:苹果官网上 iPhone 6 是 750×1334,设计稿却是 375×667,而且各设备“CSS 分辨率”都比物理分辨率小一截。这就要区分物理像素和逻辑像素。

设备物理分辨率(设备像素)

从蓝屏到彩屏、触屏再到智能手机,屏越来越清晰、越来越大。分辨率从颗粒感很重,到 720p、1080p 甚至 2K:

╬в╨┼╜╪═╝_20200322213453

物理分辨率翻倍,若仍按物理像素画图,图像会缩小一倍——总不能给每台设备出一套稿。乔布斯很早就用逻辑分辨率把这个问题按住了。

逻辑分辨率(设备独立像素)

各机物理分辨率差很多,逻辑分辨率却差不多。iPhone 4 发布会上提出 Retina:把 2×2 个物理像素当 1 个像素用,更精致但元素 CSS 大小不变。高分屏从此多了逻辑像素。逻辑像素差别不大但仍有差别,移动端页面才需要适配。

二、设备像素比与 1px 边框

DPR(device pixel ratio)= 物理像素 / 设备独立像素。CSS 写 1px 时,按 DPR 映射可能变成 2px 或 3px 物理像素;大屏上就会显得很粗,这就是经典的 1 像素边框问题。

Web 里用 window.devicePixelRatio 取 dpr;CSS 用 min-device-pixel-ratio 媒体查询。直接写 0.5px 兼容很差:

╬в╨┼╜╪═╝_20200322213632

Chrome 把 0.5px 四舍五入成 1px,Firefox / Safari 能画半像素;小于 0.5px 时 Chrome 当 0,Firefox 把不小于 0.55 当 1,Safari 把不小于 0.75 当 1。iOS 上 Chrome 能画出 0.5px,Android 5.0 原生浏览器不行。小数 px 的宽高同样不可靠。

更稳的做法是 transform: scale(0.5):

div {

    height:1px;

    background:#000;

    -webkit-transform: scaleY(0.5);

    -webkit-transform-origin:0 0;

    overflow: hidden;

}

再按 2 倍屏 / 3 倍屏媒体查询:

/* 2倍屏 */

@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {

    .border-bottom::after {

        -webkit-transform: scaleY(0.5);

        transform: scaleY(0.5);

    }

}



/* 3倍屏 */

@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {

    .border-bottom::after {

        -webkit-transform: scaleY(0.33);

        transform: scaleY(0.33);

    }

}

三、viewport 与三种适配

viewport

视口是当前可见区域,在浏览器里通常等于窗口内容区(不含菜单栏)。移动端用一个 meta 配置:

<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">

╬в╨┼╜╪═╝_20200322213528

要体验好,视口宽度必须接近理想视口:不手动缩放时最理想的布局尺寸,也就是屏幕宽度。上面这套 meta 规定宽度等于设备宽度、初始缩放 1,视觉视口就是理想视口。user-scalable=no 还可以去掉移动端点击 300ms 延迟(拓展)。

1)rem 适配

rem 相对 HTML 根元素。改根字体就能按比例改整页,又避免 em 层层复合。IE8 及更早不支持,可再写一份绝对单位兜底。

//假设我给根元素的大小设置为14px

html{

    font-size:14px

}

//那么我底下的p标签如果想要也是14像素

p{

    font-size:1rem

}

//如此即可

阿里早期的 flexible 让页面统一用 rem:把 1rem = viewWidth / 10。

// set 1rem = viewWidth / 10

function setRemUnit () {

    var rem = docEl.clientWidth / 10

    docEl.style.fontSize = rem + 'px'

}

setRemUnit();

初始化时给根元素设 font-size,其余按 rem 排,窗口变化就等比缩放,设计稿 px 再换成 rem。这是过渡方案:当年低版本 Android 的 viewport、以及 vw/vh 兼容还不齐,flexible 用 rem 模拟 vmin。按屏幕大小 100% 还原设计稿,iPhone 5 和 6 Plus 上字号实际不同;而人在相同距离上希望看到的大小接近。用户买大屏是想看更多内容,不是更大的字。纯缩放方案注定被淘汰。

2)vw / vh 布局

把视觉视口宽 window.innerWidth、高 window.innerHeight 各分成 100 份。

╬в╨┼╜╪═╝_20200322213605

和 rem 类似要做单位换算,px 转 vw 还不一定整除,会有像素差。工程上可用 postcss-px-to-viewport 在构建时自动转:

{

    loader: 'postcss-loader',

    options: {

    	plugins: ()=>[

        	require('autoprefixer')({

        		browsers: ['last 5 versions']

        	}),

        	require('postcss-px-to-viewport')({

        		viewportWidth: 375, //视口宽度(数字)

        		viewportHeight: 1334, //视口高度(数字)

        		unitPrecision: 3, //设置的保留小数位数(数字)

        		viewportUnit: 'vw', //设置要转换的单位(字符串)

        		selectorBlackList: ['.ignore', '.hairlines'], //不需要进行转换的类名(数组)

                minPixelValue: 1, //设置要替换的最小像素值(数字)

                mediaQuery: false //允许在媒体查询中转换px(true/false)

        	})

    	]

}

3)px 为主,vw 为辅,搭配 flex(推荐)

大屏手机是为了看更多内容,所以直接用 px 往往最明智。vw、rem 并非不能用,但在 flex 已经普及的今天,还死守整页等比缩放,多半是不愿做分机型适配,或不愿学新布局。

四、推荐落地流程

  • head 里设置 width=device-width 的 viewport
  • CSS 里主要用 px
  • 适当场景用 flex,或配合 vw 做自适应
  • 跨设备类型(PC ↔ 手机 ↔ 平板)用媒体查询
  • 交互差太大时考虑分成不同项目
方案 做法 适用 / 代价
1px 边框 scaleY(0.5/0.33) + 媒体查询 避免小数 px 的浏览器差异
rem / flexible 根 font-size = 屏宽/10 过渡方案,大屏字跟着变大
vw 视口 100 等分,可走 PostCSS 换算有像素差
px + flex 主体 px,弹性区域 flex/vw 大屏看到更多内容

相关阅读:flex深度剖析-解决移动端适配问题!。原文链接:https://juejin.im/post/5e6caf55e51d4526ff026a71

一句话总结:先分清物理像素、逻辑像素和 DPR,用 scale 解决 1px;适配不要迷信整页 rem 缩放,优先 viewport + px + flex,让大屏多看内容。

转载请注明来源:为什么要移动端适配
本文链接地址:https://ai.zhousir.top/?p=2462
回复 取消