Mobile Web开发奇淫巧计

Author : luckyGirl

做了一段时间的Mobile Web开发,遇到一些坑,总结一下:

HTML <meta>

HTML5 开发一个页面适配所有设备,先从配置<meta>各种标签属性开始。

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<meta name="format-detection" content="telephone=no, email=no">
<meta http-equiv="x-dns-prefetch-control" content="on">
  • viewport: 对文档的视图进行配置,示例有强制文档宽度为设备宽度;初始化缩放比例是1:1;最大缩放比例是1;不允许用户进行屏幕缩放;其他属性如minimum-scale,height等
  • apple-mobile-web-app-capable:IOS特有标签,是否允许全屏模式浏览
  • apple-mobile-web-app-status-bar-style:Safari顶端状态条颜色
  • format-detetion:格式检测,是否把数字识别为电话号码,是否识别邮箱
  • http-equiv=”x-dns-prefetch-control”:DNS Prefetch 是一种DNS预解析技术,对网页中的域名进行解析缓存,减少用户等待时间,提高用户体验

 CSS

  1. 1px边框

由于Retina屏幕的出现,设置1px的边框,实际上却显示2px,有时就会略显粗壮,用JS可以进行处理,但兼容性不好;用背景图片当改变颜色时略显麻烦不够方便。

  • 淘宝使用的是viewport+rem实现,

devicePixelRatio = 2时,输出viewport:<meta name=”viewport” content=”width=device-width, initial-scale=0.5, maximum-scale=0.5, user-scalable=no”>

devicePixelRatio = 3时,输出viewport:<meta name=”viewport” content=”width=device-width, initial-scale=0.5, maximum-scale=0.5, user-scalable=no”>

  • CSS 多背景渐变
1px 块
1px 块
.border{border:1px solid #e0e0e0;}
.border-radius{border:1px solid #e0e0e0;border-radius:4px;}
@media screen and (-webkit-min-device-pixel-ratio:2){
 .border, .border-radius{border:0;position:relative;}
 .border:after{
 content:"";
 width:100%;
 height:100%;
 position:absolute;
 top:0;
 left:0;
 background-image:-webkit-gradient(linear,left bottom,left top,color-stop(0.5,rgba(0, 0, 0, 0)),color-stop(0.5,#E0E0E0)),-webkit-gradient(linear,left top,right top,color-stop(0.5,rgba(0, 0, 0, 0)),color-stop(0.5,#E0E0E0)),-webkit-gradient(linear,left top,left bottom,color-stop(0.5,rgba(0, 0, 0, 0)),color-stop(0.5,#E0E0E0)),-webkit-gradient(linear,right top,left top,color-stop(0.5,rgba(0, 0, 0, 0)),color-stop(0.5,#E0E0E0));
-webkit-background-size:100% 1px,1px 100%,100% 1px,1px 100%;
background-siz:100% 1px,1px 100%,100% 1px,1px 100%;
background-repeat:no-repeate;
background-position: top,right,bottom,left;
padding: 1px;
-webkit-box-sizing: border-box;
z-index:10;
pointer-events: none;
}
.border-radius:before{
content:"";
top:0;
left:0;
width:200%;
height:200%;
position:absolute;
border:1px solid #e0e0e0;
-webkit-transform:scale(0.5);
-webkit-transform-origin:0 0;
padding:1px;
-webkit-box-sizing:border-box;
border-width:8px;
pointer-events:none;
}
  1. 文字截断
  •  一行文字截断

我是单行文字,放不下的会省略

.singleText{
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
  • 多行文字截断(默认2行)

我是多行文字,默认是2行,放不下的会省略

.multilineText{
display: -webkit-box;
 overflow: hidden;
 text-overflow: ellipsis;
 -webkit-box-orient: vertical;
 -webkit-line-clamp: 1;
 -webkit-box-flex: 1;
 height: inherit;
}

3. 点击后高亮

移动端点击文字或是图片,默认背景是有灰色的,这个是一般情况不希望看到的,CSS便可解决

body{
-webkit-user-select:none;
-webkit-tap-highlight-color:transparent;
}

4. 阻止旋转屏幕时自动调整字体大小

body{
-webkit-text-size-adjust:100%;
}
  1. Zepto.js tap 点透问题

Zepto.js是移动端常用的轻量级库,tap点透问题是个经典问题,出现的情景如:页面出现了个弹框,点击button触发其tap事件的同时也触发了弹框下面一层DOM元素的tap事件。解决这个问题的思路有2种,

  • 第一种:之所以在移动端使用tap而不是click,是因为在移动端浏览器中为了辨别用户是要单击还是双击,会对click事件进行300ms的延迟,为了提高用户体验,快速响应,因而采用tap。github有个比较好的解决方案fastclick,引入fastclick.js,然后在代码中执行
</pre>
$(<span class="pl-k">function</span>() {
    FastClick.attach(<span class="pl-c1">document</span>.<span class="pl-c1">body</span>);
});
<pre>
  • 第二种:由于这个本身是Zepto.js触发tap事件的机制导致,由如下源代码可见tap是通过监听绑定在document上的touchstart事件进行模拟并是在冒泡到document时触发的,而在此之前用户触摸到屏幕的touchstart和离开屏幕touchend是会触发click事件的,因此在tap完成后延迟300ms的click事件紧接着触发,从而产生点透问题。
$(document).ready(function(){
 var now, delta

 $(document.body).bind('touchstart', function(e){
 now = Date.now()
 delta = now - (touch.last || now)
 touch.el = $(parentIfText(e.touches[0].target))
 touchTimeout && clearTimeout(touchTimeout)
 touch.x1 = e.touches[0].pageX
 touch.y1 = e.touches[0].pageY
 if (delta > 0 && delta <= 250) touch.isDoubleTap = true
 touch.last = now
 longTapTimeout = setTimeout(longTap, longTapDelay)
 }).bind('touchmove', function(e){
 cancelLongTap()
 touch.x2 = e.touches[0].pageX
 touch.y2 = e.touches[0].pageY
 }).bind('touchend', function(e){
 cancelLongTap()

 // double tap (tapped twice within 250ms)
 if (touch.isDoubleTap) {
 touch.el.trigger('doubleTap')
 touch = {}

 // swipe
 } else if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
 (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30)) {
 touch.el.trigger('swipe') &&
 touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
 touch = {}

 // normal tap
 } else if ('last' in touch) {
 touch.el.trigger('tap')

 touchTimeout = setTimeout(function(){
 touchTimeout = null
 touch.el.trigger('singleTap')
 touch = {}
 }, 250)
 }
 }).bind('touchcancel', function(){
 if (touchTimeout) clearTimeout(touchTimeout)
 if (longTapTimeout) clearTimeout(longTapTimeout)
 longTapTimeout = touchTimeout = null
 touch = {}
 })
 })

 ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){
 $.fn[m] = function(callback){ return this.bind(m, callback) }
 })

知道问题所在,我们就可以使用touchend代替tap并阻止默认的行为:

$('#tapElement').on('touchend',fuction(e){
    //do something
    e.preventDefault;
});

Mobile Web开发坑还有很多,慢慢积累与沉淀吧,欢迎大家来完善!

转载请表明原文:LoveCicy

standard

Have your say