记录一下移动端开发常用的功能和遇到的问题

147 阅读5分钟

h5适配计算

什么是viewport

早期移动端的viewport与pc的viewport是一个概念,导致小屏体验不佳,后来苹果引入可视视窗(visual viewport)和布局视窗(layout viewport)。这两个视窗是透视的效果,想象下layout viewport是一张大的不能改变大小和角度的图片。我们透过visual viewport对layout viewport进行观察。观察距离远点(用户的缩小页面功能)就可以一次性看到这个大图。或者近点(用户的放大页面功能)可以看到一部分。你能改变这个透视框的方向,但这张大图片的大小和形状都不会改变。

我们在<meta name="viewport" /> 设置的其实是layout-viewport,使得layout viewport==visual viewport,达到ideal viewport效果,使得viewport刚好完美覆盖屏幕,因此适配方案的时候,这一句最重要。

px rem vw的转换

  • 默认情况下根元素的font-size为 1rem = 16px,但为了方便换算,我们通常设置 1rem = 100px
  • 以750px的设计稿为例,则可以得出 750px = 7.5rem
  • 相当于100vw=7.5rem那么1rem = 100vw / 7.5 = 13.3333vw,所以设置根元素的font-size为13.3333vw
  • 而在页面样式中,直接将设计稿中的px除以100就是对应的rem值
  • 若要兼容旧浏览器,则需要写入响应式布局,例如:
// 相当于 320 / 7.5 = 42.667px
@media screen and (max-width: 320px) {
  html {
    font-size: 42.667px;
    font-size: 13.3333vw;
  }
}

// 相当于375 / 7.5 = 48px,以下同理
@media screen and (min-width: 321px) and (max-width: 375px) {
  html {
    font-size: 48px;
    font-size: 13.3333vw;
  }
}

@media screen and (min-width: 376px) and (max-width:393px) {
    html {
        font-size: 52.4px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 394px) and (max-width:412px) {
    html {
        font-size: 54.93px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 413px) and (max-width:414px) {
    html {
        font-size: 55.2px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 415px) and (max-width:480px) {
    html {
        font-size: 64px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 481px) and (max-width:540px) {
    html {
        font-size: 72px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 541px) and (max-width:640px) {
    html {
        font-size: 85.33px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 641px) and (max-width:720px) {
    html {
        font-size: 96px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 721px) and (max-width:768px) {
    html {
        font-size: 102.4px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 769px) and (max-width:852px) {
    html {
        font-size: 113.4px;
        font-size: 13.3333vw
    }
}
@media screen and (min-width: 853px) {
    html {
        font-size: 130.4px;
        font-size: 13.3333vw
    }
}

不同的设计稿,可以参考下面的表格

设计稿大小(单位 px)html 的 font-size(单位 vw)
37526.666666
75013.333333
32031.25
64015.625

viewport缩放比例设置

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />

其他可能使用到的meta标签配置

<meta name="screen-orientation" content="portrait"> //Android 禁止屏幕旋转
<meta name="full-screen" content="yes">             //全屏显示
<meta name="browsermode" content="application">     //UC应用模式,使用了application这种应用模式后,页面讲默认全屏,禁止长按菜单,禁止收拾,标准排版,以及强制图片显示。
<meta name="x5-orientation" content="portrait">     //QQ强制竖屏
<meta name="x5-fullscreen" content="true">          //QQ强制全屏
<meta name="x5-page-mode" content="app">            //QQ应用模式

电话号码识别

在 iOS Safari (其他浏览器和 Android 均不会)上会对那些看起来像是电话号码的数字处理为电话链接,比如:

  • 7 位数字,形如:1234567
  • 带括号及加号的数字,形如:(+86)123456789
  • 双连接线的数字,形如:00-00-00111
  • 11 位数字,形如:13800138000

关闭识别

<meta name="format-detection" content="telephone=no" />

开启识别

<a href="tel:123456">123456</a>

邮箱识别(Android)

安卓上会对符合邮箱格式的字符串进行识别,我们可以通过如下的 meta 来管别邮箱的自动识别

<meta content="email=no" name="format-detection" />

同样地,我们也可以通过标签属性来开启长按邮箱地址弹出邮件发送的功能:

<a mailto:dooyoe@gmail.com">dooyoe@gmail.com</a>

chrome实机调试

  • 电脑上访问chrome://inspect/#devices
  • 在手机中安装Chrome浏览器
  • 若是调试微信内置网页,需要先在手机中打开这个地址:debugxweb.qq.com/?inspector=…
  • 安卓手机开启USB调试,通过USB连接电脑即可

底部使用固定定位遮住内容

给底部内容设置padding-bottom撑开

判断页面所在的环境

判断是否移动端

function isMobile(){
    if(window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
        return true; // 移动端
    }else{
        return false; // PC端
    }
}

判断是否微信环境

function getIsWxClient() {
  const ua = navigator.userAgent.toLowerCase();
  const reg = /MicroMessenger/i;
  return reg.test(ua);
}

判断是否横屏/竖屏

// 判断是否横屏竖屏
function hengshuping() {
    // 竖屏
    if (window.orientation == 180 || window.orientation == 0) {
        alert('竖屏')
    }
    // 横屏
    if (window.orientation == 90 || window.orientation == -90) {
         alert('横屏')
    }
}
window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize',hengshuping,false);

判断是否IOS环境

function isIos() {
  const u = navigator.userAgent;
  return !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
}

判断浏览器环境

let isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

// Firefox 1.0+
let isFirefox = typeof InstallTrigger !== 'undefined';

// Safari 3.0+ "[object HTMLElementConstructor]"
let isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification));

// Internet Explorer 6-11
let isIE = /*@cc_on!@*/false || !!document.documentMode;

// Edge 20+
let isEdge = !isIE && !!window.StyleMedia;

// Chrome 1 - 79
let isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);

// Edge (based on chromium) detection
let isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1);

// Blink engine detection
let isBlink = (isChrome || isOpera) && !!window.CSS;


let output = 'Detecting browsers by ducktyping:<hr>';
output += 'isFirefox: ' + isFirefox + '<br>';
output += 'isChrome: ' + isChrome + '<br>';
output += 'isSafari: ' + isSafari + '<br>';
output += 'isOpera: ' + isOpera + '<br>';
output += 'isIE: ' + isIE + '<br>';
output += 'isEdge: ' + isEdge + '<br>';
output += 'isEdgeChromium: ' + isEdgeChromium + '<br>';
output += 'isBlink: ' + isBlink + '<br>';
document.body.innerHTML = output;

iphone字体重叠问题

在iphone8下设置字体容器的宽度,发现字体会重叠,将容器宽度取消,问题解决

移动端获取scrollTop高度

不同手机的浏览器获取scrollTop存在兼容问题,需要取几个可能取到的属性的最大值

const scrollTop = Math.max(document.documentElement.scrollTop,document.body.scrollTop,window.scrollY);
const scrollHeight = Math.max(document.documentElement.scrollHeight || document.body.scrollHeight)

关于小米手机自带浏览器背景图加载失败

自带浏览器可能对一些字段进行了屏蔽(例如广告之类的),在对图片进行命名时,尽量简单命名,避开某些关键字

scss less移动端函数转换

// scss
@function pxToRem($size) {
    @return calc($size / 100) * 1rem
}
// less
.pxToRem(@px) {
    @var: unit(@px / 100)
    @rem: ~'@{var}rem'
}
// 使用
.box {
    width: .pxToRem(300px)[@rem]
}