移动端开发
前言
web移动端也就是我们常说的H5页面,现如今手机屏幕尺寸不一,我们在开发中需要对不同型号及尺寸的手机屏幕做相应的适配, 以保证它们所表现出基本一致的显示效果。 下文将主要介绍web移动端一些基本知识和常见的适配方案以及移动端需要注意的问题。
基本知识
viewport视口
- visual viewport:屏幕的可视区域,即物理像素尺寸(window.innerWidth)
- layout viewport:布局视口,即DOM宽度(document.documentElement.clientWidth),移动设备默认的viewport,默认的布局视口宽度要远大于屏幕宽度
- idea viewport:理想适口,使布局视口就是可见视口(visual viewport宽度 = ideal viewport宽度 / scale缩放值)
如何进行视口设置呢?
我们需要不允许用户手动缩放,设置缩放值为1,即visual viewport宽度 = ideal viewport宽度
<meta name="viewport" content="width=device-width, inital-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
物理像素(physical pixel)
物理像素又被称为设备像素,单位是px,比如iPhone6的 (750 x 1334px) 常说的一倍屏、二倍屏(Retina)、三倍屏,指的是设备以多少物理像素来显示一个CSS像素
独立像素DIP(Device independent Pixel)
设备独立像素,也称为逻辑像素。 CSS像素就可以看做是设备的独立像素,例如,在Retina屏的iphone上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素,2x2个像素当1个像素使用,这样一组被称作“设备独立像素”,因此有如下关系:
CSS像素 = 设备独立像素 = 逻辑像素
设备像素比DPR(device pixels ratio)
是指在移动开发中1个css像素占用多少设备像素,如2代表1个css像素用2x2个设备像素来绘制。在移动端浏览器中以及某些桌面浏览器中,window对象有一个devicePixelRatio属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。 DPR = 物理像素(设备像素) / 逻辑像素(css像素/设备独立像素)
适配方案
百分比&媒体查询
媒体查询至少需要进行如下设置:
<meta name="viewport" content="width=device-width"/>
最常见的媒体查询
/* iPhone5 */
@media screen and(min-width: 320px){...}
/* mi5/5s/6 */
@media screen and(min-width: 360px){...}
/* iPhone6/7/8/X */
@media screen and(min-width: 375px){...}
/* iPhone6/7/8 Plus */
@media screen and(min-width: 414px){...}
2
3
4
5
6
7
8
9
10
11
rem方案
- rem (font size of the root element)相对于根元素(即html元素)font-size计算值,即 1rem = html中设置的font-size
原理:主要通过js动态修改 html 的 fontSize
/**
* 动态计算根元素fontSize
*/
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- postcss-plugin-px2rem
推荐在项目中使用自动转换插件,例如postcss-plugin-px2rem,它能自动的帮我们实现px到rem的转换,从此解放人脑计算,艾玛真香!推荐配合 autoprefixer 使用,添加浏览器前缀到CSS(某些第三方库样式错乱)如vue-cli3中配置:
// vue.config.js
loaderOptions: {
postcss: {
plugins: [
require('autoprefixer')({ // 推荐配合使用 autoprefixer 添加浏览器前缀到CSS
// browsers: ['last 20 versions'],
overrideBrowserslist: ['last 20 versions'], // 记得这里要把 browsers 改为 overrideBrowserslist,autoprefixer 新版本的写法有变
}),
require('postcss-plugin-px2rem')({
rootValue: 100, //换算基数
exclude: /(node_module)/, //排除前端UI框架内的px也转换成rem
mediaQuery: false, //允许在媒体查询中转换px。
}),
],
},
},
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vw/vh方案
vh、vw方案即将视觉视口宽度 window.innerWidth和视觉视口高度 window.innerHeight 等分为 100 份。和rem类似也是相当麻烦需要做单位转化, 推荐插件 postcss-px-to-viewport 自动实现px到vw的转化
// vue.config.js
loaderOptions: {
postcss: {
plugins: [
require('autoprefixer')({ // 推荐配合使用 autoprefixer 添加浏览器前缀到CSS
// browsers: ['last 20 versions'],
overrideBrowserslist: ['last 20 versions'], // 记得这里要把 browsers 改为 overrideBrowserslist,autoprefixer 新版本的写法有变
}),
require('postcss-px-to-viewport')({
viewportWidth: 375, //视口宽度
viewportHeight: 1334, //视口高度
unitPrecision: 3, //设置的保留小数位数
viewportUnit: 'vw', //设置要转换的单位
selectorBlackList: ['.box', '.wrapper'], //不需要进行转换的类名
minPixelValue: 1, //设置要替换的最小像素值
mediaQuery: false //允许在媒体查询中转换px
],
},
},
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
其他
1px问题
1px在Retina屏下不仅仅是一个像素点。css中一个1x1的点,在dpr为2时是2x2的点, 在dpr为3时是3x3的点, 这就会导致某些边框看起来比较粗。解决方案是对边框进行缩放:transform: scale(0.5)
300ms 延迟
移动浏览器 会在 touchend 和 click 事件之间,等待 300 - 350 ms,判断用户是否会进行双击手势用以缩放文字。
解决方案可以使用 fastClick库