网页端适配(手机网页适配) REM方案 PX2REM方案 缩放方案 媒体查询 图片适配

REM(推荐)

首先我们知道rem是根据页面根节点的字体大小来计算dom的宽高的,那么我们就可以根据窗口的大小动态改变根节点的字体大小,而页面中的元素的宽高都使用rem作为单位来适配不同的窗口。

页面中添加

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
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0"/>
</head>
<style>
html {font-size: 10px}

body {
font-size: 1.6rem;
}
</style>
<script>
// 防抖
function debounce(fn, wait) {
let timeout = null
return function() {
if(timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait);
}
}
// 计算
function resize(){
const mHtml = document.documentElement;
const width = mHtml.clientWidth;
// 假如设计图的宽度是400
mHtml.style.fontSize = 10 * (width / 400) + "px";
}
resize();
window.addEventListener('resize', debounce(resize, 100))
</script>

这里我根节点的默认宽度使用的是10px,这样是方便换算为rem,

而效果图的计算宽度默认为400px,是因为400px是在所有主流手机宽度的中间值

这样我们就可以在蓝湖上把效果图的宽度设置为400px,所有的宽高直接除以10换算为rem即可。

PX2REM+REM(推荐)

安装依赖

1
npm i postcss-px2rem --save -dev

Postcss的配置文件.postcssrc.js

找到项目根目录下的.postcssrc.js文件

1
2
3
4
5
6
7
8
9
10
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
"autoprefixer": {
"browsers": ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 8']
},
'postcss-px2rem':{'remUnit':10} //配置rem基准值
}
}

remUnit: 10 代表 1rem = 10px; 所以当你一个12px值时,它会自动转成 (12/10)rem

然后使用上面的适配就行

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
<style>
html {font-size: 10px}

body {
font-size: 1.6rem;
}
</style>
<script>
// 防抖
function debounce(fn, wait) {
let timeout = null
return function() {
if(timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait);
}
}
// 计算
function resize(){
const mHtml = document.documentElement;
const width = mHtml.clientWidth;
// 假如设计图的宽度是1920
mHtml.style.fontSize = 10 * (width / 1920) + "px";
}
resize();
window.addEventListener('resize', debounce(resize, 100))
</script>

但是内联样式并没有被处理

我们可以手动更改为计算后的rem。

如果在动态绑定样式并且手动计算比较难算的时候使用下面的方式。

转换方法

1
2
3
4
5
6
7
8
function px2rem(px){
if(/%/ig.test(px)){ // 有百分号%,特殊处理,表述pc是一个有百分号的数,比如:90%
return px
}else{
return (parseFloat(px) / 10) + 'rem'
}
}
Vue.prototype.$px2rem = px2rem // 放到全局

使用

1
<div :style="{fontSize:$px2rem('16px')}"></div>

媒体查询适配(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
body {
background-color: green;
}
@media screen and (min-width: 1200px ) {
body {
background-color: hotpink;
}
}

@media screen and (min-width: 761px) and (max-width: 1199px) {
body {
background-color: yellow;
}
}

@media screen and (max-width: 760px) {
body {
background-color: pink;
}
}

页面缩放(不推荐)

整个页面缩放

注意

如果框架的弹窗位置是通过JS计算的,那么会发生偏移,就不推荐这种方式。

有这么一个情况,项目已经开发很久了,都是按1920*1080做的,这样在小屏幕上就会显示不好看,但是换成rem就要所有页面都进行更改就太麻烦了,我们就可以使用zoom方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="app_outer">
</div>
<script>
function resize() {
const width = document.body.clientWidth;
const widthZoom = width / 1920;
console.info("width:" + width);
console.info("widthZoom:" + widthZoom);
let app_outer = document.getElementById("app_outer");
app_outer.style.zoom = widthZoom;
app_outer.style.height = 100 / widthZoom + "vh";
}

window.onload = function () {
resize();
};

window.onresize = function () {
resize();
}
</script>

注意

缩放后100vh就不再是窗口的高度了,要除以缩放比例。

页面中类似于

1
height: calc(100vh - 100px);

也要改为

1
height: calc(100% - 100px);

上面的例子是根据宽度进行适配的,当然也可以根据高度适配,直接获取高度获取到的是0,所以可以使用下面的方式。

获取窗口的高度

1
2
3
4
5
6
7
8
9
function getClientHeight() {
let clientHeight = 0;
if (document.body.clientHeight && document.documentElement.clientHeight) {
clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight);
} else {
clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight);
}
return clientHeight;
}

内部缩放

如果内部的宽高是确定的,但是会大于外层的DIV,我们想自适应。

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
44
45
46
47
48
49
50
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ZOOM</title>
</head>
<body>
<div id="outer_div">
<div id="inner_div"></div>
</div>
<script>
function resize() {
const width = document.getElementById("outer_div").offsetWidth;
const zoom = width / 1920;
console.info("width:" + width);
console.info("zoom:" + zoom);
let inner_div = document.getElementById("inner_div");
inner_div.style.zoom = zoom;
}

window.onload = function () {
resize();
};

window.onresize = function () {
resize();
}
</script>

<style>
body {
margin: 0;
padding: 0;
}

#outer_div {
background: red;
width: 100vw;
height: 100vh;
overflow: hidden;
}

#inner_div {
background: #0a9caf;
width: 1920px;
height: 1080px;
}
</style>
</body>
</html>

图片适配

如果尺寸的比例不一样 那么图片就会变形

我们可以设置这个属性

1
2
3
4
5
img {
width: 100%;
height: 100%;
object-fit: cover;
}

相关概念

px、em、rem

  • px是固定像素,一旦设置了就无法因为适应页面而改变。
  • em是rem相对于px更具有灵活性,他们是相对于长度单位的变化而变化,更适应于响应式布局
  • em相对于父元素字体大小的倍数
  • rem相对于根元素字体大小的倍数

Viewport 基础

视觉窗口:Viewport是移动端特有。这是一个虚拟的区域,承载网页的。

一个常用的针对移动网页优化过的页面的 viewport meta 标签大致如下:

1
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0"/>

其中

  • width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)
  • height:和 width 相对应,指定高度
  • initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例
  • maximum-scale:允许用户缩放到的最大比例
  • minimum-scale:允许用户缩放到的最小比例
  • user-scalable:用户是否可以手动缩放