关于移动端适配的几个简单解决办法(vue)

关于移动端适配的几个简单解决办法(vue)

对移动端适配原理进行简单介绍,并提供几个适用于 vue 项目的移动端适配解决方案。

基本概念

首先要了解一下关于适配的基础知识。
移动 web 开发之像素和 DPR
适配的基础知识
总结:

  1. px 又称像素。有两种像素概念,一种是网页设计中使用的 css 像素(逻辑像素),一种是原生移动系统使用的设备像素。一个 CSS 像素对应多少个设备像素是根据当前的缩放比例(dpr)来决定的,即 css 像素可能包含多个设备像素。
  2. 物理像素的大小在不同设备上不一定相等。体现为屏幕像素密度不同(ppi),可以对比一下电脑和手机上的像素点大小。
  3. DPR 设备像素比 DPR = 设备像素 / CSS像素(某一方向上),dpr 为 2 的设备,一个 css 像素含有 4 个物理像素,dpr 为 3 的设备,一个 css 像素含有 9 个物理像素。
  4. 我们在 viewport(虚拟布局窗口)上面布局,然后通过 meta 标签 <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> 做一些设置之后渲染到设备上。
  5. css 像素数跟设备大小没关系,因为不同的设备单个物理像素是不一样的。css 像素数 = 分辨率宽/dpr。例如 iphone6 dpr=2 分辨率 750x1334,打印它的宽 为 375px。红米 note2A 分辨率 1920x1080 dpr=3 打印为 360px。另外 iphone6plus 分辨率 1920x1080 打印是 414px,原因是它的 dpr=2.6。
  6.  为什么推荐使用 rem 来做适配单位CSS3 的 REM 设置字体大小

rem 适配方式概念

rem 适配方式并不是只有一种,这种方式的核心理论是 动态计算 页面宽度/一个比例值(比如 10 或者 15)= 1rem。这里放一个 demo,以 iphone6 设计稿里面元素的尺寸除以 100 得到的就是最终的 rem 值。

1
2
3
4
5
6
7
8
9
10
(function() {
document.addEventListener(
"DOMContentLoaded",
function(e) {
document.getElementsByTagName("html")[0].style.fontSize =
window.innerWidth / 7.5 + "px";
},
false
);
})();

所以哪怕不是除以 7.5 而是其他的比例转化为 rem 或者不同的页面宽度计算和 js 引入,也是属于 rem 方式的一种。

目标问题

适配需要解决问题:

  1. 1px 边框问题
  2. 图片适配
  3. 字体适配
  4. 元素自适应
  5. 横竖屏适配

适配方案

介绍关于像素单位的基本知识,原因在于适配方案大部分都是基于单位来进行适配的。
 直接使用 px 方式做适配的方案这里就不说了,重点放在 rem 适配方式和 vw 适配方式上面。同时秉着简单、方便的原则,将会尽量避免与第三方 UI 库发生冲突,以便于开发者借助 UI 库迅速开发。

rem 适配一

第一种 rem 适配,可以参考使用 Flexible 实现手淘 H5 页面的终端适配
这种方式引入lib-flexible这个库,具体适配方法是先根据设备的 dpr 进行页面缩放,然后再使用 rem 进行适配。
这种方式的好处是根据 dpr 进行了缩放,所以 1px 边框以及一些适配问题都迎刃而解,效果显示细腻。
坏处是缩放相当于改变了原先的 css 单位,所以绝大部分 UI 库都无法使用,也即这种方式可能适用于从 0 开始做东西。而且细节部分较多,不留神可能容易出错。这种方式是比较早的方式,淘宝基本已经不用了,部分开发者还是有使用这种方式。

vw 适配方案

后来手淘团队又出了 vw 适配方案。再聊移动端页面的适配
这种方案使用 vw 单位做适配。理论其实跟 rem 方案差不多,区别就是使用了原生支持的 vw 而不用 rem,不过我现在不是很看好它的兼容性问题,手淘团队为了兼容做了一套方案,暂时不过多研究,这种方案以后可能会成为适配主流。

rem 适配二

这个方式其实就是普通的 rem 适配方案在 vue 项目里的应用。秉着前端自动化的原则,使用 postCSS 插件对单位自动做了处理,这样既能与 UI 库和平共存,又能自动 px 转 rem 单位。

  1. 新建一个 vue 项目
  2. npm i postcss-pxtorem --save-dev
  3. 在项目根目录下 .postcssrc.js 文件里面添加
1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
plugins: {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
autoprefixer: {},
// 刚才安装的插件 如下
"postcss-pxtorem": {
rootValue: 16,
propList: ["*"]
}
}
};
  1. 项目根目录 main.js 里面引入一个 js,内容
1
2
3
4
5
6
7
8
9
10
(function() {
document.addEventListener(
"DOMContentLoaded",
function(e) {
document.getElementsByTagName("html")[0].style.fontSize =
window.innerWidth / 23.4375 + "px";
},
false
);
})();
  1. 这样 样式单位使用 px 就会被转换成 rem 了。
    100px
    100pxToRem
    100px代码
    postcss-pxtorem
    而且这个插件也可以做一些配置,例如设置 写 Px 则不会进行转换等。
  2. 这样基于 vue 的自动化适配基本就完成了。通过设置在 iPhone6 尺寸下 1rem = 16px,不会影响 UI 库的使用(也可以设置为 14px,调节上方 23.4375 即可),也通过 postcss 插件进行了自动转化。

几个适配问题的解决方法

1px 边框问题

移动 web 1 像素边框 瞧瞧大公司是怎么做的
7 种方法解决移动端 Retina 屏幕 1px 边框问题
移动 web 1px 边框解决方案
总结:如果是 ios7 之后的版本,那么可以直接用 0.5px,不过安卓就 emmm。
比较好的几个办法:

  1. 伪元素缩放
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #test1 {
    margin-top: 30px;
    width: 50px;
    height: 50px;
    position: relative;
    }
    #test1:before {
    position: absolute;
    content: "";
    width: 200%;
    height: 200%;
    top: 0;
    left: 0;
    border: 1px solid #000;
    transform: scale(0.5);
    transform-origin: 0 0;
    box-sizing: border-box;
    pointer-events: none;
    }

    /* 圆角 */
    .div::after {
    content: "";
    width: 200%;
    height: 200%;
    position: absolute;
    top: 0;
    left: 0;
    border: 1px solid #bfbfbf;
    border-radius: 4px;
    -webkit-transform: scale(0.5, 0.5);
    transform: scale(0.5, 0.5);
    -webkit-transform-origin: top left;
    }
  2. 图片替换
  3. 颜色渐变
  4. 阴影

图片和字体适配

使用 rem 适配方式二,一般不管 dpr=2 还是 dpr=3,设置图片原先一半的尺寸就是高清。dpr=2 和 dpr=3 差别很小。
字号也是平常的设计稿尺寸除以 2。如果移动设备屏幕太大可能会导致字号显示过大,如有需要单独进行样式设置。

img 标签图片适配

这个方法直接使用 css 的 srcset 和 sizes 属性进行响应式渲染,具体使用:

1
2
3
4
5
6
<img
src="../assets/test@2x.jpg"
srcset="../assets/test@2x.jpg 128w, ../assets/test@3x.jpg 256w"
sizes="128px"
alt=""
/>

一个 src 保底兼容 IE,然后根据 sizes 计算的宽度来命中使用哪个图片。
支持 chrome38+ 但是 IE 不支持
参考响应式图片 srcset 全新释义 sizes 属性 w 描述符

背景图倍图适配

用 stylus 做的例子,使用 css 预编译器的方法,将路径和类型传递过去:

1
2
3
4
5
6
7
8
9
10
11
bg(url, type) {
background-image: url(url+"."+type);

@media only screen and (-webkit-min-device-pixel-ratio: 2) {
background-image: url(url+"@2x."+type);
}

@media only screen and (-webkit-min-device-pixel-ratio: 3) {
background-image: url(url+"@3x."+type);
}
}
1
2
3
4
5
6
#test {
width: 100px;
height: 100px;
background-color: yellow;
bg('../assets/test', 'jpg');
}

这样就能根据 dpr 选择图片。

横竖屏适配

H5 游戏开发:横屏适配
移动端 H5 解惑-页面适配(二)

参考文章

一些参考文章上面已给出链接。
移动端高清、多屏适配方案 - 移动端 H5 - 前端乱炖
掘金 🐂🍺dalao-图文并茂 10 大重点讲解移动端适配必备知识

Author: XavierShi
Link: https://blog.xaviershi.com/2018/07/12/移动端适配几个简单解决办法(vue)/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.