移动Web适配

基础概念

设备像素或逻辑像素

指设备能控制显示的最小物理单位,意指屏幕上一个个的点。

CSS像素或设备独立像素

指CSS样式代码中使用的逻辑像素,即 px(在iPhone中单位为pt)。

像素密度(PPI)

指设备能控制显示的最小物理单位,意指屏幕上一个个的点(=设备像素或逻辑像素)。PPI 越高,分辨率也就越高。

像素比(DPR)

像素比 = 设备像素 / CSS像素。

rem

rem 是一个相对单位,区别于 em(相对于父亲的字体大小) ,它是相对于 html 的字体大小单位。


适配方案

这里列举两种方案,其原理相同:

设置样式的长度单位为 rem,然后通过监听浏览器窗口大小的变化,实时改变根元素字体大小,那么 1rem 所对应的 px 值也随之变化,达到适配各种终端的目的。

postcss-pxtorem + flexible.js

这个方法适用于 WebStorm。

1. 安装 postcss-pxtorem
1
npm i postcss-pxtorem@5.1.1 --save

注意,高版本的 postcss-pxtorem 会导致报错。

2. 配置 package.json 文件

在 package.json 文件中添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
"postcss": {
"plugins": {
"autoprefixer": {},
"postcss-pxtorem": {
"rootValue": 16,
"propList": ["*"],
"minPixelValue": 2,
"selectorBlackList": [],
"unitPrecision": 5
}
}
}

其中,plugins 字段中包含的是 postcss 的各种插件。我们来看 postcss-pxtorem 的配置项:

  • rootValue:根元素字体大小,浏览器默认为 16px
  • propList:哪些属性需要转换成 rem,这里是全部
  • minPixelValue:就是最小转换单位,这里为 2px,小于 2px 不进行转换
  • selectorBlackList:是一个对 css 选择器进行过滤的数组,比如设置为[‘fs’],那么例如 fs-xl 类型,里面有关 px 的样式将不被转化,这里也支持正则
  • unitPrecision:表示转换为 rem 后保留几位小数

postcss-pxtorem 的作用是将 px 转换为 rem,即使我们的代码中用的是 px 单位,在编译时也会自动将 px 转换为 rem。它转换的标准基于 “rootValue” ,rootValue 的值为多少那么 1rem 就等于多少。

3. 安装 flexible.js
1
npm install lib-flexible --save

打开 flexible.js,编辑源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
// if (width / dpr > 540) {
// width = 540 * dpr;
// } 将这行代码注释
var rem = width / 10; // 根据需求将 10 换成其他数值
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}

// 设置 body 的字体大小,目的是使根字体大小不影响页面默认字体大小
// 我们可以将 12 改为 16(浏览器默认字体大小)
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 12 * dpr + 'px';
} else {
doc.addEventListener('DOMContentLoaded', function(e) {
doc.body.style.fontSize = 12 * dpr + 'px';
}, false);
}
4. 在 main.js 文件中引入 flexible.js
1
import 'lib-flexible/flexible'

在 flexible.js 中,1rem 等于屏幕宽度的 1/10,假如设计稿的宽高为 1920*1080,那么 1rem = 192px。现在我们要以设计稿的标准定义一个宽高均为 300px 的 div,如果我们把 rootValue 的值设为 16,那么编译时将 300px 转换为了 18.75rem,而此时 1rem = 192px,那么最后渲染出来的 div 宽高为 1440px。但是如果把 rootValue 的值设为 192px,那么就正常了。

注意:只有写在 <style> 标签中的样式才能被转换为 rem,内联样式不被转换。


flexible.js + cssrem

这个方法适合用于 VS Code。

1. 引入视口标签
1
<meta name="viewport" content="width=device-width,user-scalable=no initial-scale=1.0">
2. 引入 flexible.js
1
<script src="./flexible.js"></script>

源码如下:

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
35
36
37
38
39
40
41
42
43
(function flexible(window, document) {
var docEl = document.documentElement;
var dpr = window.devicePixelRatio || 1;

// adjust body font size
function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = 12 * dpr + "px";
} else {
document.addEventListener("DOMContentLoaded", setBodyFontSize);
}
}
setBodyFontSize();

// set 1rem = viewWidth / 10
function setRemUnit() {
var rem = docEl.clientWidth / 10;
docEl.style.fontSize = rem + "px";
}

setRemUnit();

// reset rem unit on page resize
window.addEventListener("resize", setRemUnit);
window.addEventListener("pageshow", function (e) {
if (e.persisted) {
setRemUnit();
}
});

// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement("body");
var testElement = document.createElement("div");
testElement.style.border = ".5px solid transparent";
fakeBody.appendChild(testElement);
docEl.appendChild(fakeBody);
if (testElement.offsetHeight === 1) {
docEl.classList.add("hairlines");
}
docEl.removeChild(fakeBody);
}
})(window, document);

配置与上面相似。

3. 安装 cssrem 插件

在 VS Code 的插件选项中搜索,然后点击安装。

找到 cssrem 插件的设置,按照需要对里面的配置项进行配置。

设置完之后,在打 px 的时候会有转换成 rem 的提示框,选择对应 rem 即可。

大功告成!!!