当前位置:首页 > 资讯 > 正文

常见的移动端H5页面开发遇到的坑和解决办法

常见的移动端H5页面开发遇到的坑和解决办法

经研究发现是devicePixelRatio作怪,因为手机分辨率太小,如果按照分辨率来显示网页字会非常小,所以苹果就把iPhone 4的960640分辨率在网页里只显示了480320,这样devicePixelRatio=2;现在android比较乱,有1.5/2/3等,想让图片在手机里显示更为清晰必须使用2x的背景图来代替img标签(一般情况都是用2倍),例如一个div的宽高是100100,背景图必须得200200,然后background-size:contain;,这样显示出来的图片就比较清晰了;代码如下:

 
 

这点是手机站开发者都应该知道的,就是设置meta中的viewport;有些手机站有如下声明:

 

设置DTD的方式是XHTML的写法,假如页面运用的是h5可以不用设置DTD,直接声明

使用viewport使页面禁止缩放,通常把user-scalable设置为0来关闭用户对页面视图缩放的行为

 

为了更好的兼容,我们使用完整的viewport设置

 
 

apple-mobile-web-app-capable是设置Web应用是否以全屏模式运行;语法:

 
 

html5提供了自动调用拨号的标签,只要在a标签的href中添加tel:就可以了

 

format-detection可以启动或禁用自动识别页面中的电话号码;语法:

 
 

h5网页input的type设置为number一般会产生三个问题:

问题1:maxlength属性不好用

解决,我目前用的是js

 

问题2:form提交的时候默认取整

因为form提交默认做了表单验证,step默认是1,要设置step属性,假如保留2位小数,写法如下:

 

问题3:部分安卓手机出现样式问题

去除input中这些默认样式:

 

去除input默认样式的方法:

 
 

问题1:右对齐实现

设置如下属性

 

问题2:唤起select的option展开

zepto方式:

 

原生js方式:

 

问题3:禁用select默认箭头

::-ms-expand修改表单控件下拉箭头,设置隐藏并使用背景图片来修饰

 

问题4:使用appearance改变webkit浏览器的默认外观

 
 

移动端的点击事件都会有300ms延迟,是因为浏览器在等待你是否执行双击,但此延迟导致用户体验不好,解决这个问题,我们的方案如下:

1.尽量都使用touch事件来替换click事件,例如用touchend事件(推荐)

2.用preventDefault阻止a标签的click

3.用script标签引入fastclick库去除延迟,实验证明fastclick比tap要快

4.zepto的touch模块,tap事件也是可以解决在click的延迟问题

5.延迟一定的时间(300ms+)来处理事件(不推荐)

6.以上一般都能解决,实在不行就换成click事件

7.触摸事件的响应顺序为touchstart-->touchmove-->touchend-->click,也可以通过绑定ontouchstart事件,加快对事件的响应,解决300ms延迟问题

8.若移动设备兼容性正常的话(IE/Firefox/Safari(IOS 9.3)及以上)只需加上下面meta标签即可把viewport设置成设备的实际像素,就不会有300ms的延迟

 

click事件的延迟会导致移动端点透问题

案例如下:

 

div是绝对定位的蒙层且z-index高于a,我们给div绑定tap事件:

 

我们点击蒙层时div正常消失,但是当我们在a标签上点击蒙层时,发现a链接被触发,这就是所谓的点透事件

原因:touchstart早于touchend早于click,即click的触发是有300ms左右延迟的,也就是说tap触发之后蒙层隐藏click没有触发,300ms之后由于蒙层消失click触发到了下面的a链接上;解决方案同上面的click事件延迟

由于自动播放网页中的音频或视频会给用户带来困扰或不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用JS的触发播放,必须由用户来触发才播放;解决方法思路:先通过用户touchstart触碰触发播放并暂停(让音频开始加载),后面用JS再操作就没问题了;解决代码:

 
 

当今的手机端,屏幕分辨率各有不同,为了让页面可以兼容各款手机,解决方案如下:

1.设置meta标签viewport属性,使其无视设备的真实分辨率,直接通过dpi在物理尺寸和浏览器之间重设分辨率,从而达到能有统一的分辨率的效果,并且禁止掉用户缩放

 

2.使用rem进行屏幕适配,设置好root元素的font-size大小,然后在开发的时候所有与像素有关的布局统一换成rem单位;针对不同的手机使用媒体查询对root元素font-size进行调整

解决方法:

1.尽可能地使用合成属性transform和opacity来设计CSS3动画,不使用position的left和top来定位

2.开启硬件加速

 

目前像Chrome/Filefox/Safari/IE9+以及最新版本Opera都支持硬件加速,当检测到某个DOM元素应用了某些CSS规则时就会自动开启,从而解决页面闪白,保证动画流畅

3.各种应用的webview(例如微信)在遇到有大量图片时会出现img和background-image互相错乱的情况,6和6plus更为严重,目前暂时的解决方法也是动态给所有用到图片的元素加上

4.页面中的滑动刷新在某些手机中出现卡顿滑不动的情况,以下给出可行的解决方案:

a.关闭probeType属性(传说是因为这个启用监听滚动状态的很耗性能,关闭这个属性滑动就会流畅很多)

 

b.给scroll元素增加css样式:

解决方法如下:

1.父元素设置为

2.父元素设置为 等

这里两种方法都是通过设置css属性将浮动元素的父元素变成BFC(块级格式化上下文)元素,使子元素高度可以撑开父元素;不过最好使用方法1,因为inline-block元素本身会自带一些宽高度撑开其本身

BFC产生的条件:

1.html根元素

2.float的值不为none

3.display的值为inline-block/table-cell/table-caption

4.position的值为absolute或fix

5.overflow的值不为visible

BFC约束规则:

1.生成BFC元素的子元素会一个接一个的放置;垂直方向上他们的起点是一个包含块的顶部,俩个相邻子元素之间垂直距离取决于元素margin特性,在BFC中相邻的块级元素外边距会折叠

2.生成BFC元素的子元素中每个子元素的外边距和包含块的左边界相接触(对于从右到左的格式化,右外边距和右边界相接触),除非这个子元素也创建一个新的BFC(如它自身也是一个浮动元素)

3.BFC的区域不会与float的元素区域重叠

4.计算BFC高度时浮动元素也参与计算

5.BFC就是页面上一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然

我们在写css常见的一些问题都可以由上面两条推出,例如:

1.Block元素与父元素同宽,所以Block元素竖直方向上垂直排列。

2.竖直方向上有的Block元素margin会重叠,水平方向不会。

3.浮动元素会尽量接近左上方或右上方。

4.为父元素设置overflow:hidden或浮动父元素,则父元素会包含其浮动的子元素。

BFC有很多实际的用处,例如防止相邻block的竖直margin重叠(塌陷)

点击浏览器的回退有时候不会自动执行js,特别是在mobilesafari中;这与往返缓存(bfcache)有关系,解决方法:

 
 

1.fixed定位

ios下fixed元素容易定位出错,软键盘弹出时影响fixed元素定位,而android下不会;ios4下不支持position:fixed

解决方案:使用[Iscroll],如:

 

2.position定位

Android下弹出软键盘弹出时影响absolute元素定位;解决方案如下:

 

3.安卓手机端软键盘弹出顶起页面布局

BODY被顶起的解决办法:

 
 

问题1:音频/视频写法

 

问题2:ios系统手机无法自动播放音频/视频

这个是苹果系统限制默认不允许自动播放音频/视频,需要点一下触发play()事件才能播放;那么我们可以在页面onload后触发播放事件:

 

到这里一般都可以播放音乐了,如果还不行很有可能是微信的限制

问题3:微信的限制

如果是微信的限制,这时需要调用微信接口,页面先引入:

 

然后JS写入微信事件:

 

小结

1.audio元素的autoplay属性在IOS及Android上无法使用,在PC端正常

2.audio元素没有设置controls时,在IOS及Android会占据空间大小,而在PC端Chrome是不会占据任何空间

问题4:Safari浏览器自动播放

 

问题5:ios系统不支持动画暂停样式(animation-play-state)

H5页面一般都会有BGM,也会提供一个旋转的音乐图标供用户开启关闭音乐;我们希望当用户点击音乐按钮时图标停止旋转,再点图标顺着之前停止的位置继续跑动画;animation-play-state是最简便的方式,然而ios不支持

目前的解决方案是:音乐图标负责跑动画,图标父级元素负责记录停止时的转动值

问题6:ios系统摇一摇播放音效事件无效

在实现摇晃(引用了封装好的shake.js)手机触发某一音效这个需求时,发现在微信中音效没有被触发;后面找到原因:在ios里并没有把自定义摇晃事件shake当成交互动作,而要播放音效需要用户有交互动作;没有交互音效就没被加载,那么我们先加载音效,结合上面的微信接口:

 

load()过之后再调用play()即可听到音效

解决:加入样式可禁止用户进行,ios和一般的安卓都可以解决,唯独小米自带浏览器还有问题

 

添加完这段代码后在IOS上会有问题,这时发现input框无在输入内容了;造成这个原因是这个属性,解决方法就是在css文件中同时设置一下input的属性,如下:

 
 
 

overflow-x:auto在iOS有兼容问题,解决方法:

 
 

ios用户点击一个链接会出现一个半透明灰色遮罩,如果想要禁用可设置-webkit-tap-highlight-color的alpha值为0去除灰色半透明遮罩

android用户点击一个链接会出现一个边框或者半透明灰色遮罩,不同生产商定义出来效果不一样,可设置-webkit-tap-highlight-color的alpha值为0去除部分机器自带的效果

winphone系统点击标签产生的灰色半透明背景能通过设置去掉

特殊说明:有些机型去除不了,如小米2,对于按钮类还有个办法,不使用a或input标签,直接用div标签

 

在winphone下使用如下代码

 
 

这种情况是以前遇到的,这里也说下;主要会发生在webview里多一点,当点击后退时页面以缓存形式出现,而不是刷新后的,很多情况下这不是你预期的效果,解决方法是用js:

 

onpageshow每次页面加载都会触发,无论是从缓存中加载还是正常加载,这是他和onload的区别;persisted判断页面是否从缓存中读出

有些机型的搜索input控件会自带close按钮(一个伪元素),而通常为了兼容所有浏览器我们会自己实现一个,此时去掉原生close按钮的方法为

 

如果想使用原生close按钮又想使其符合设计风格,可以对这个伪元素的样式进行修改

input的placeholder会出现文本位置偏上的情况:PC端设置line-height等于height能够对齐,而移动端仍然是偏上,解决方案时是设置css

 
 
 

说明:除非你先使用apple-mobile-web-app-capable指定全屏模式,否则这个meta标签不会起任何作用;如果content设置为default,则状态栏正常显示;如果设置为blank,则状态栏会有一个黑色的背景;如果设置为blank-translucent,则状态栏显示为黑色半透明;如果设置为default或blank,则页面显示在状态栏的下方,即状态栏占据上方部分;页面占据下方部分,二者没有遮挡对方或被遮挡;如果设置为blank-translucent,则页面会充满屏幕,其中页面顶部会被状态栏遮盖住(会覆盖页面20px高度,而iphone4和itouch4的Retina屏幕为40px);默认值是default。

用input search做模糊搜索的时候,在键盘里输入关键词,会通过ajax后台查询然后返回数据;用input监听键盘keyup事件,在安卓手机浏览器中是可以的,但是在ios手机浏览器中很慢,用输入法输入后并未立刻执行相应的keyup事件,只有删除之后才能响应;经查发现,IOS的输入法(不管是第三方还是自带)能检测到英文或数字的keyup,但检测不到中文的keyup,在输入中文后需要点回退键才开始搜索;解决办法是用html5的oninput事件去代替keyup,通过如下代码达到类似keyup的效果;oninput是HTML5的标准事件,对检测textarea,input:text,input:password和input:search这几个元素的内容修改后立即被触发,不像onchange事件要失去焦点才触发;但oninput事件在IE9以下版本不支持,需要用IE特有的onpropertychange事件替代,这个事件在用户界面改变或者使用脚本直接修改内容两种情况下都会触发,有以下几种情况:

1.修改了input:checkbox或input:radio元素的选择中状态,checked属性发生变化

2.修改了input:text或textarea元素的值,value属性发生变化

3.修改了select元素的选中项,selectedIndex属性发生变化

 
 

设置如下属性

 
 

iOS浏览器横屏时会重置字体大小,设置text-size-adjust为none可以解决iOS上的问题,但桌面版Safari的字体缩放功能会失效,因此最佳方案是将text-size-adjust为100%

 
 

可以通过正则去掉

 
 

针对此种情况只需对不触发click事件的元素添加一行css代码即可

 
 
 

这种写法在安卓和pc上都正常的,唯独在ios手机上会显示NAN,调试发现,ios上只支持格式:

 

调试发现2016/05/31等同2016-05-31 00:00:00,也就是说ios默认就是从0开始计算的,我们不需要设置后面的时分秒为00:00:00

iOS(safari)有时候某个标签绑定点击事件无效,加上空的onclick=""就好了,如:

1.display:flex;

最新写法:;酷派,三星等安卓手机需加上兼容,否则子元素中无法撑开宽度

2.flex-wrap:wrap;

三星手机中flex盒模型的子元素必须用;如果是block则三星手机不会换行,如果是inline元素(比如)则宽度不会撑开仍然表现为内联元素

3.flex-direction: column;

三星手机不支持,无法使用使子元素自动在最下

4.flex元素中嵌套flex

三星手机出错,必须父元素为flex,而其它祖先元素为block

部分安卓机中使用text-indent属性会使元素宽度超过100%,加上box-sizing:border-box;修复正常

1.同一个页面里要是有两个二维码,长按扫描总是只能扫出左侧/第一个二维码

解决:可视区域内只能出现一个二维码

2.使用meta标签缩放页面后长按二维码图片无反应

解决:使用以下代码后就能长按识别二维码了~