首页
技术分享
实用工具 发布文章 新浪微博 Github

随着移动互联网的快速发展,在移动页面的交互形式也越来越复杂,这给前端带来很多烦恼,本文总结了最近一年研究移动端相关的页面开发以及性能优化得一些小技巧,”望君可以少几分忧愁“。

高性能 CSS3 动画

尽可能的让动画元素不在文档流中,以减少重排

1
2
position: fixed;
position: absolute;

尽可能多的利用硬件能力,如使用3D变形来开启GPU加速

1
2
3
4
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);

如动画过程有闪烁(通常发生在动画开始的时候),可以尝试下面的Hack:

1
2
3
4
5
6
7
8
9
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
backface-visibility: hidden;

-webkit-perspective: 1000;
-moz-perspective: 1000;
-ms-perspective: 1000;
perspective: 1000;

尽可能少的使用box-shadowsgradients
box-shadowsgradients往往都是页面的性能杀手,尤其是在一个元素同时都使用了它们。


消除 transition闪屏

两个方法:

1
2
3
4
5
-webkit-transform-style: preserve-3d;
/*设置内嵌的元素在 3D 空间如何呈现:保留 3D*/

-webkit-backface-visibility: hidden;
/*(设置进行转换的元素的背面在面对用户时是否可见:隐藏)*/

高频触发事件 采用事件节流 或加以控制

比如要绑定一个touchmove的事件,正常的情况下类似这样

1
2
3
$('div').on('touchmove', function(){
// code...
});

而如果中间的code需要处理的东西多的话,FPS就会下降影响程序顺滑度,而如果改成这样

1
2
3
4
5
$('div').on('touchmove', function(){
setTimeout(function(){
//.….code
},0);
});

把代码放在setTimeout中,会发现程序变快.


移动端 HTML5 audio autoplay 失效问题

由于自动播放网页中的音频或视频,会给用户带来一些困扰或者不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放,必须由用户来触发才可以播放。

解决方法思路:先通过用户 touchstart 触碰,触发播放并暂停(音频开始加载,后面用 JS 再操作就没问题了)。

1
2
3
4
document.addEventListener('touchstart', function () {
document.getElementsByTagName('audio')[0].play();
document.getElementsByTagName('audio')[0].pause();
});


利用paddingmargin得百分比特性做响应式元素

paddingmargintopbottom值设置百分比参数,百分比是相对于宽度计算得距离,利用此特性有助于移动端定位元素位置。


使伪类:active生效

要CSS伪类 :active 生效,只需要给 document 绑定 touchstarttouchend 事件 解决方法:加入下方js,激活:active。

1
document.addEventListener('touchstart',function(){},false);

添加分享到朋友圈缩略图

微信分享链接时,自动抓取缩略图方法: 需要一张300*300的图片, 并添加在 body下,微信会自动抓取这张图来作为缩略图显示,格式如下:

1
2
3
<div id="wx_pic" style="display:none;">
<img src="assets/images/share.jpg">
</div>

iOS Safari 委托在document或者body上的事件失效

Safari 对click事件定义只能冒泡到body下面的子节点,所以委托在document上得click事件不会被触发!
解决方法为body得子节点添加click事件既可以解决。

1
$("body").children().click(function () {});


iOS Safari 双击后事件失效bug

bug 出现在弹出层双击空白区域后,浏览器scroll下移一部分,页面点击事件失效。
解决方法:弹出层禁止touchstart


小米内置浏览器 z-index 失效

小米内置浏览器z-index失效多数产生在具有css3动画,或者设置translate3d属性的场景下。
解决方法: 为想要提升的层级添加tanslate3d(0,0,0)后在设置z-index解决。


zepto.js 在Android手机中,通过$(window).width()获取宽度值不正确bug

部门安卓手机通过Zepto.js提供得 $(window).width()$(window).height()获取浏览器视图宽度与实际宽度不一致。
解决方法:通过document.documentElement.clientWidth 获取宽度。

1
2
var pageWidth = document.documentElement.clientWidth;
var pageHeight = document.documentElement.clientHeight;

魅族内置浏览器 动态修改className渲染失效

魅族内置浏览器 js修改页面元素className 后渲染失效,问题出现在display:block; 和 部门css3样式;
解决办法:触发scroll强制浏览器重绘。

1
2
document.body.scrollTop = 2;
document.body.scrollTop = 0;

关于iOS系统中,中文输入法输入英文时,字母之间可能会出现一个六分之一空格

可以通过正则去掉

1
this.value = this.value.replace(/\u2006/g, '');


关闭iOS键盘首字母自动大写

在iOS中,默认情况下键盘是开启首字母大写的功能的,如果启用这个功能,可以这样:

1
<input type="text" autocapitalize="off">

ios中去掉元素被触摸时产生的半透明灰色遮罩

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

1
a,button,input,textarea{-webkit-tap-highlight-color: rgba(0,0,0,0;)}

去掉Android中元素被点击时产生的边框

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

1
2
3
4
a,button,input,textarea{
-webkit-tap-highlight-color: rgba(0,0,0,0;)
-webkit-user-modify:read-write-plaintext-only;
}

-webkit-user-modify有个副作用,就是输入法不再能够输入多个字符
另外,有些机型去除不了,如小米2对于按钮类还有个办法,不使用a或者input标签,直接用div标签


去除移动端输入框内阴影

在iOS上,输入框默认有内部阴影,但无法使用 box-shadow 来清除,如果不需要阴影,可以这样关闭:

1
2
3
4
5
input,
textarea {
  border: 0; /* 方法1 */
  -webkit-appearance: none; /* 方法2 */
}


移动端禁止选中内容

如果你不想用户可以选中页面中的内容,那么你可以在css中禁掉:

1
2
3
4
5
.user-select-none {
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all (移动端不需要) */
-ms-user-select: none; /* IE 10+ */
}


手机拍照和上传图片

1
2
3
4
<!-- 选择照片 -->
<input type="file" accept="image/*">
<!-- 选择视频 -->
<input type="file" accept="video/*">

使用总结:
ios 有拍照、录像、选取本地图片功能
部分android只有选取本地图片功能


伪元素css3动画失效

在安卓微信内置浏览器中,对一个伪元素做css3动画失效。

解决方法:
不用伪元素,换成标签。


webview中viewport固定宽度全屏显示方法

由于一些移动端游戏或互动形式 布局(元素)需要固定大小,又需要自适应屏幕,
可以通过设置视口宽度等于固定值让浏览器自动缩放页面的方法来实现。

1
<meta name="viewport" content="width=640,initial-scale=1,target-densitydpi=device-dpi,minimum-scale=1,maximum-scale=1,user-scalable=1">

其中的width=640就是网页内容区的宽度,需要在不同手机上刚好全屏显示,target-densitydpi=device-dpi设置后,css中的1px就会等于物理像素中的1px。
补充:由于safari浏览器不支持 target-densitydpi = device-dpi,所以加入JS代码自动调整缩放比例,调整后的代码:

1
2
3
4
5
6
7
<meta name="viewport" id="WebViewport" content="width=640,initial-scale=1,target-densitydpi=device-dpi,minimum-scale=0.5,maximum-scale=1,user-scalable=no"> 

<script language="javascript">
if(screen.width < 640) {
document.getElementById('WebViewport').setAttribute('content', 'width=640,initial-scale=' + screen.width / 640 + ',target-densitydpi=device-dpi,minimum-scale=0.1,maximum-scale=1,user-scalable=no');
}
</script>


三星note2(低版本系统手机)css3动画fadeIn导致div内滚动闪屏

bug描述:页面渐入动画 fadeIn,导致设置 fixed 属性的div内滚动闪屏,滑动后背景闪白,受影响手机可到note4,但闪烁频率没有那么高。

1
2
3
4
5
@keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
animation: fadeIn .6s both;

解决方法:去掉所有淡入效果,或者针对三星手机去掉css3动画,或者弹出层不要有滚动条。


Listview 太长引起的手机性能问题

问题表现:
内存中存留的DOM结构太多,导致滚动的 Listview 后面,点击响应会延迟,甚至无响应。

解决方法是:
1.在 li 外面包裹一层,将前面页码的 dom 移除,同时设置外层容器的高度(这样不至于影响滚动条)
2.下拉滚动翻页过程中,对之前页码的数据进行隐藏。
获取最后一个隐藏的元素,得到隐藏的页码,判断后2页中的第5条数据是否在屏幕中。

1
2
3
4
5
6
7
8
var $lastHidden = $teacherList.find('li[data-show="hidden"]').last(),
lastHiddenPage = $lastHidden.data('page');
var $midle = $teacherList.find('li[data-page="' + (lastHiddenPage + 2) + '"]').eq(4);
if($midle && $midle.offset() && $midle.offset().top > $(document.body).scrollTop()){
// 页面中最后一个元素显示在屏幕中
// problem: 向上滑动过快,这里有卡顿
$teacherList.find('li[data-page="' + lastHiddenPage + '"]').css('visibility', 'visible').data('show', 'visible');
}

IOS 5+快速回弹滚动问题

问题表现:
IOS5新特性-webkit-overflow-scrolling: touch可以启动快速回弹滚动(fast bounce-scroll)效果,但是它会阻止渲染直到滚动结束。

影响: 1.从不滚动状态到滚动状态(反之亦然),因为要先初始化滚动状态才开始渲染,虽然很短暂,但也是有delay的,所以出现闪屏
2.列表滚动过程中,需要等到滚动结束之后,后面的元素才会渲染出来

解决方法是:
1.启动硬件加速,可以用-webkit-transform: translate3d(0,0,0),这个hack可以解决大部分问题
2.用min-height,直接杜绝滚动状态改变,从而防止闪屏问题(已解决详情页闪屏问题)