前言
最近在公司写一个混合 App 项目, 页面基本全部都是用 H5 完成, 嵌入到原生 webview 下. 发现一个问题, 在 iPhone 6 下 苹果手机的状态栏会挡住页面, 导致页面下移, 样式错乱, 最后网上查找了些解决办法, 加了一条 meta 标签解决了问题. 今天特来总结下常用的移动端开发需要注意的 meta 标签及一些小技巧.
- viewport
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
这个是移动端页面开发必备的标签, 用来调整布局视口同视觉视口一致, 禁止页面缩放等.
apple-mobile-Web-App-capable
apple-mobile-Web-App-capable 是设置 Web 应用是否以全屏模式运行.
语法:
<meta name="apple-mobile-web-app-capable" content="yes">
说明:
如果 content 设置为 yes,Web 应用会以全屏模式运行, 反之, 则不会. content 的默认值是 no, 表示正常显示. 如果选择全屏模式运行, 则会删除默认的苹果工具栏和菜单栏.
我开篇遇到的问题就是通过设置该 meta 标签解决的.
设置顶部状态栏的颜色
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
说明:
这个标签起作用的前提是 必须事先开启了全屏模式运行 webapp, 即 第二条的 meta 标签必须同步指定, 否则这个标签不起作用.
如果 content 设置为 default, 则状态栏正常显示. 如果设置为 blank, 则状态栏会有一个黑色的背景. 如果设置为 blank-translucent, 则状态栏显示为黑色半透明. 如果设置为 default 或 blank, 则页面显示在状态栏的下方, 即状态栏占据上方部分, 页面占据下方部分, 二者没有遮挡对方或被遮挡. 如果设置为 blank-translucent, 则页面会充满屏幕, 其中页面顶部会被状态栏遮盖住(会覆盖页面 20px 高度, 而 iphone4 和 itouch4 的 Retina 屏幕为 40px). 默认值是 default.
webapp 添加到主屏后的标题(iOS 6 新增)
<meta name="apple-mobile-web-app-title" content="title">
设置缓存
<meta http-equiv="Cache-Control" content="no-cache" />
手机页面通常在第一次加载后会进行缓存, 然后每次刷新会使用缓存而不是去重新向服务器发送请求. 如果不希望使用缓存可以设置 no-cache.
format-detection
format-detection 启动或禁用自动识别页面中的电话号码.
语法:
<meta name="format-detection" content="telephone=no">
说明:
默认情况下, 设备会自动识别任何可能是电话号码的字符串. 设置 telephone=no 可以禁用这项功能.
html5 调用安卓或者 iOS 的拨号功能
html5 提供了自动调用拨号的标签, 只要在 a 标签的 href 中添加 tel: 就可以了.
拨打手机直接如下:
<a href="tel:15677776767">点击拨打 15677776767</a>
PS: 如果遇到这种情况失效, 可以在页面头部 添加 上一条 meta 标签, content 设置为 yes.
iPhone 及 iPad 下输入框默认出现内阴影.
- Element{
- -webkit-appearance: none;
- }
移动端滑动页面绝对定位元素出现抖动
这个问题自己网上找了一些解决办法, 仅供参考.
给 body 设置高度 100%
- body,HTML{
- widht:100%;
- height:100%;
- }
如果是项目中已经做好的页面, 有其他特效, 直接设置这个属性, 可能对页面的其他功能造成影响.
如果使用此法, 本地调试效果不好, 建议不要使用.
给固定定位的元素添加 transform 属性
transform:translateZ(0);
或者
transform:translate3d(0,0,0);
外层嵌套一个盒子
多加一层盒子, 外层 fixed 固定定位, 内层的设置绝对定位 absolute;
- <div style='position: fixed;'>
- <div style='position: absolute'>
- ...
- </div>
- </div>
iPhone 下 input 框光标过长
input 输入框在 iPhone 下 光标过长, Android 显示正常.
方法:
调低 input 标签的 line-height 样式值.
iOS 下 页面滑动卡顿, 不流畅
在内容出现滚动的元素上设置一条 CSS 样式, 实现惯性滚动和弹性效果.
- {
- -webkit-overflow-scrolling: touch;
- }
-webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果, 它有两个值:
auto: 使用普通滚动, 当手指从触摸屏上移开, 滚动会立即停止.
touch:
使用具有回弹效果的滚动, 当手指从触摸屏上移开, 内容会继续保持一段时间的滚动效果. 继续滚动的速度和持续的时间和滚动手势的强烈程度成正比. 同时也会创建一个新的堆栈上下文.
页面顶部固定定位元素或底部固定定位元素遮挡页面部分内容.
方法一:
给最外层的 div 加上 padding-bottom, 值为 固定定位元素高度;
方法二:
利用伪元素, 给最外层 div 添加伪元素 after, 设置高度为 固定定位元素高度.
- .wrapper::after{
- content: '';
- height: '固定定位元素高度';
- }
禁止复制, 选中文本
- Element {
- -webkit-user-select: none;
- -moz-user-select: none;
- -khtml-user-select: none;
- user-select: none;
- }
iOS 中 input 键盘事件 keyup,keydown,keypress 支持不是很好
用 input search 做模糊搜索的时候, 在键盘里面输入关键词, 会通过 Ajax 后台查询, 然后返回数据, 然后再对返回的数据进行关键词标红. 用 input 监听键盘 keyup 事件, 在安卓手机浏览器中是可以的, 但是在 iOS 手机浏览器中变红很慢, 用输入法输入之后, 并未立刻相应 keyup 事件, 只有在通过删除之后才能相应!
解决办法:
可以用 html5 的 oninput 事件去代替 keyup
- <input type="text" id="test">
- <script type="text/javascript">
- document.getElementById('test').addEventListener('input', function(e){
- var value = e.target.value
- ....
- })
- </script>
然后就达到类似 keyup 的效果!
webview 下部分 JavaScript 代码没有执行, 比如 alert()等.
解决办法:
webview 只是一个承载体, 各种内容的渲染需要使用 webviewChromClient 去实现, 所以 set 一个默认的基类 WebChromeClient 就行.
PS: 这部分需要原生开发协助设置一个 基类 WebChromeClient, 代码:
WebView.setWebChromeClient()
移动端点击 300ms 延迟
300ms 尚可接受, 不过因为 300ms 产生的问题, 我们必须要解决. 300ms 导致用户体验并不是很好, 解决这个问题, 我们一般在移动端用 tap 事件来取代 click 事件.
推荐两个 JS, 一个是 fastclick, 一个是 tap.JS.
关于移动端点击延迟处理方案, 详细叙述请看: 移动端点击延迟处理方案
移动端点击穿透问题
案例如下:
- <div id="haorooms">
- 点透事件测试
- </div>
- <a href="http://www.baidu.com">
- 百度
- </a>
div 是绝对定位的蒙层, 并且 z-index 高于 a. 而 a 标签是页面中的一个链接, 我们给 div 绑定 tap 事件:
- $('#haorooms').on('tap',function(){
- $('#haorooms').hide()
- })
我们点击蒙层时 div 正常消失, 但是当我们在 a 标签上点击蒙层时, 发现 a 链接被触发, 这就是所谓的点透事件.
原因:
touchstart 早于 touchend 早于 click. 亦即 click 的触发是有延迟的, 这个时间大概在 300ms 左右, 也就是说我们 tap 触发之后蒙层隐藏, 此时 click 还没有触发, 300ms 之后由于蒙层隐藏, 我们的 click 触发到了下面的 a 链接上.
解决办法:
尽量都使用 touch 事件来替换 click 事件. 例如用 touchend 事件(推荐).
用 fastclick, 详情看上面 GitHub 仓库.
用 preventDefault 阻止 a 标签的 click.
延迟一定的时间 (300ms+) 来处理事件 (不推荐).
以上一般都能解决, 实在不行就换成 click 事件.
下面介绍一下 touchend 事件, 如下:
- $("#haorooms").on("touchend", function (event) {
- event.preventDefault()
- })
iOS 中, 中文输入法输入英文时, 字母之间可能会出现一个六分之一空格
可以通过正则去掉
this.value = this.value.replace(/\u2006/g, '')
解决 iOS 中 video 标签视频自动全屏播放问题
给 video 标签添加 属性:
- <!-- 针对 iOS8,9 下生效 -->
- <video webkit-playsinline="webkit-playsinline">
- </video>
- <!-- ios10 及以上 -->
- <video playsinline="playsinline">
- </video>
PS: 如果是内嵌入 webview 下 还需要原生开发的伙伴添加以下支持代码:
webView.allowsInlineMediaPlayback = YES;
移动端点击链接发送邮件
<a href="mailto:pubdreamcc@qq.com?subject=TestObject">pubdreamcc@qq.com</a>
点击后直接给 pubdreamcc@qq.com 发邮件, 主题为: TestObject .
PS: 如果遇到这种情况失效, 可以在页面头部 添加 一条 meta 标签, content 设置为 yes.
<meta name="format-detection" content="email=yes">
移动端滚动穿透
描述:
在打开的弹窗或者遮罩层上滚动, 会影响到下层的 body 元素的滚动. 体验很不好.
解决办法:
一般思路是在打开弹框或遮罩层的时候, 获取 HTML 的 scrollTop, 给 body 改为 fixed 定位, top 值为负的 scrollTop 值. 关闭弹框的时候, 把 fixed 定位去掉. 还原 scrollTop 值.
移动端布局方式
这个基本是我们做移动开发首先需要确定的一个方案, 我总结为一句话:
经典的 REM 布局与新秀 VW 布局
当然还有常见的比如 弹性盒子(flex) 都可以.
不过需要说的是, 淘宝 flexible.JS 布局的作者已经推荐我们选用 vw 布局.
这部分大家可以自己网上查阅相关资料, 我这里就不多做累述了.
来源: https://www.cnblogs.com/cs96/p/11440142.html