工作时制作移动端的技巧

简单的利用JS来判断页面是在手机端还是在PC端打开的方法

1
2
3
4
5
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
window.location.href = "https://www.baidu.com/";
} else {
window.location.href = "http://news.baidu.com/";
}

在微信浏览器关闭当前页面的方法

  • 需要在微信公众号签名才能够使用
1
WeixinJSBridge.call('closeWindow')

移动端图片模糊的问题

  • 在移动端需要使用PC端两倍尺寸的图片,然后用background-size:50%;来还原本来的尺寸,这样移动端的图片才会清晰,不模糊

移动端调试工具

一个移动端真机调试:browser-sync

使用经验

input placeholder问题

在chrome 模拟移动端调试时,显示的非常正常,但是在真机上,placeholder里面的内容明显靠上,非常的不美观

在国外网站,对这个属性的兼容性处理,那就是不要设计input的line-height或者设置line-height为normal即可,

试了一下,虽然在谷歌模拟调试里稍微偏上,但是在“真机上”正常垂直居中~

line-height

line-height经常用于文字居中,不同手机显示效果不一样。

有时需要不是用line-height和height相同来进行居中,使用其他方法居中

实现自定义原生控件的样式

由于select移动端原生样式很丑,但是原生弹出样式是符合我们设计的原则

解决方法:将原本select 设置为透明,z-index设置高~再用一个比较好看的样式‘假装’在表面

移动端使用innerHtml绘制

使用innerHTML绘制大段,之后想获取HTML的ID节点,事实上是获取不到的,这种问题在动态创建DOM会经常发生

这也是一个神器的问题,博主自己写了一个移动端轮播插件,在chrome上浏览非常正常,但到了真机上却显示空白,各种百度,最后才发现这么坑的地方…

解决方案:尝试了很多方法之后,老老实实在页面直接用html结构,如果有更好的方法,也请告诉我。

300ms延迟

方案一:禁用缩放
在HTML文档头部包含如下meta标签时:

1
2
<meta name="viewport" content="user-scalable=no"/>
<meta name="viewport" content="initial-scale=1,maximum-scale=1"/>

缺点——就是必须通过完全禁用缩放来达到去掉点击延迟的目的,然而完全禁用缩放并不是我们的初衷,我们只是想禁掉默认的双击缩放行为,这样就不用等待300ms来判断当前操作是否是双击。

方案二:更改默认的视口宽度

1
<meta name="viewport" content="width=device-width"/>

如果设置了上述meta标签,那浏览器就可以认为该网站已经对移动端做过了适配和优化,就无需双击缩放操作了。
这个方案相比方案一的好处在于,它没有完全禁用缩放,而只是禁用了浏览器默认的双击缩放行为,但用户仍然可以通过双指缩放操作来缩放页面。

兼容性问题:
对于方案一和方案二,Chrome是率先支持的,Firefox紧随其后,然而令Safari头疼的是,它除了双击缩放还有双击滚动操作,如果采用这种两种方案,那势必连双击滚动也要一起禁用。

方案三:引入fastclick插件(最佳)

点击穿透

问题常见发生场景: 假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。

这是因为在移动端浏览器,事件执行的顺序是touchstart > touchend > click。

而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转。

解决思路:

1.不要混用touch和click

2.消耗掉touch之后的click

解决方法:

1.只用touch 把页面内所有click全部换成touch事件( touchstart 、’touchend’、’tap’),注意:a标签的href也是click,需要换成js的跳转。

2.改动最小——350ms后再隐藏B元素

虚拟键盘导致fixed元素错位

fixed元素一定会伴随虚拟键盘的出现,但是虚拟键盘只是“贴”在了viewport上,表面上不会对dom产生“任何”影响,但是这个时候fixed元素表现却变得怪异起来,会错位。

解决原理:虚拟键盘弹出时将fixed元素设置为static,虚拟键盘消失时候设置回来。

解决方案:由于虚拟键盘出现并未抛出事件,而检测scroll或者resize事件,皆会有一定延迟,会出现闪烁现象。则当前获取焦点元素为文本元素,就将fixed元素设置为static。

移动端手势

手指放在屏幕上:ontouchstart 手指在屏幕上滑动:ontouchmove 手指离开屏幕:ontouchend

原理:

1.在touchstart事件触发时, 记录手指按下的时间startTime,本次滑动的初始位置initialPos。

2.在touchmove事件触发时, 记录当前位置nowPosition(实时移动元素),滑动距离movePosition(当前位置nowPosition与初始位置initialPos的差值),判断正负数再决定是左还是右移动。

3.在touchend事件触发时, 记录手指离开屏幕的时间endTime,获得手指在屏幕上停留的时间(endTime-startTime),滑动距离movePosition

判断是否滑动:
如果停留时间少于300ms,则认为是快速滑动,无论滑动距离是多少,都到下一页
滑动距离与‘容器’ 大小进行比较,若超过‘容器’大小的1/3,则到下一页

iphone动态生成html元素click失效

这个也是神奇的坑,找了很久资料,也没有很原理的解释。
解决方法: 为绑定click的元素增加css样式 cursor:pointer;

腾讯移动端字体最佳规范设置

1
2
3
body {
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", STHeiti, "Microsoft Yahei", Tahoma, Simsun, sans-serif;
}

基础交互

设置全局的CSS样式,避免图中的长按弹出菜单与选中文本的行为

1
2
3
4
5
6
7
a, img {
-webkit-touch-callout: none; /* 禁止长按链接与图片弹出菜单 */
}
html, body {
-webkit-user-select: none; /* 禁止选中文本(如无文本选中需求,此为必选项) */
user-select: none;
}

移动性能(腾讯移动web开发规范)

要考虑Android低端机与2G网络场景下性能
发布前必要检查项

  • 所有图片必须有进行过压缩
  • 考虑适度的有损压缩,如转化为80%质量的jpg图片
  • 考虑把大图切成多张小图,常见在banner图过大的场景

加载性能优化, 达到打开足够快

  • 数据离线化,考虑将数据缓存在 localStorage
  • 初始请求资源数 < 4 注意!
  • 图片使用CSS Sprites 或 DATAURI
  • 外链 CSS 中避免 @import 引入
  • 考虑内嵌小型的静态资源内容
  • 初始请求资源gzip后总体积 < 50kb
  • 静态资源(HTML/CSS/JS/IMAGE)是否优化压缩?
  • 避免打包大型类库
  • 确保接入层已开启Gzip压缩
  • 尽量使用CSS3代替图片
  • 初始首屏之外的图片资源需延迟加载 注意!
  • 单页面应用(SPA)考虑延迟加载非首屏业务模块

运行性能优化, 达到操作足够流畅

  • 避免 iOS 300+ms 点击延时问题 注意!
  • 缓存 DOM 选择与计算
  • 避免触发页面重绘的操作
  • Debounce连续触发的事件(scroll/resize),避免高频繁触发执行
  • 尽可能使用事件代理,避免批量绑定事件
  • 使用CSS3动画代替JS动画
  • 避免在低端机上使用大量CSS3渐变阴影效果,可考虑降级效果来提升流畅度
  • HTML结构层级保持足够简单,推荐不超过 5 个层级
  • 尽能少的使用CSS高级选择器与通配选择器
  • Keep it simple

在线性能检测评定工具使用指南

  • 访问 Google PageSpeed 在线评定网站
  • 在地址栏输入目标URL地址,点击分析按钮开始检测
  • 按 PageSpeed 分析出的建议进行优化,优先解决红色类别的问题

border-1px简单实现

原理:使用min-device-pixel-ratio配合伪类呈现的border进行scaleY缩放处理:

1
2
3
<div class="box border-1px">
<p>test</p>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.border-1px {
position: relative;
}

.border-1px:after {
content: "";
display: block;
position: absolute;
left: 0;
right: 0;
bottom: 0;
width: 100%;
border-top: 1px solid #CCC;
}

/* 重点 */
@media (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) {
.border-1px:after {
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}

@media (min-device-pixel-ratio: 1.5), (-webkit-min-device-pixel-ratio: 1.5) {
.border-1px:after {
-webkit-transform: scaleY(0.7);
transform: scaleY(0.7);
}
}