移动端开发


2020-7-12 移动端

前言

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"/>
1

物理像素(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"/>
1

最常见的媒体查询

/* 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){...}
1
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);
1
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。
            }),
        ],
    },
},
1
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
        ],
    },
},
1
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库

Last Updated: 7/18/2020, 10:59:45 AM