ghost click in mobile browser

本文深入探讨了在移动端浏览器中普遍存在的幽灵点击问题,分析了其产生的原因及对用户体验的影响。文中详细介绍了不同浏览器如何处理幽灵点击,并提供了一系列解决方案,包括使用JavaScript阻止默认行为、调整页面缩放设置和实施点击消除技术。

原网址:http://ariatemplates.com/blog/2014/05/ghost-clicks-in-mobile-browsers/

Ghost clicks in mobile browsers

Ghost clicks are not new in mobile browsers, there is already literature on the web and some solutions to get rid of them (see resources at the end), but it is a complex problem and browsers manage them in different ways. So, let’s review the full problem and see how it is possible to address it.

What are ghost clicks ?

In any touch device, mobile browsers emulate click events when the screen is touched. It is useful to be compatible with websites developed for mouse interaction, and it is needed because there are no native touch events such as tap, swipe, double-tap, etc.
One problem is that in all these browsers, a double tap on the screen triggers a zoom in. In that case, no click event should be fired as the user is obviously not “clicking”. As a consequence, after the first tap, the browser must wait a while to be sure that a second tap for zooming is not happening.

So, here is what happens when the screen is taped:

  1. A touchstart event is fired as soon as a finger touches the screen.
  2. A touchend event is fired as soon as the finger leaves the screen.
  3. The browser waits around 300ms for another tap.
  4. If not, a click event is fired. This is the ghost click.

Issues with ghost clicks

This 300ms delay makes mobile websites to response slowly, and degrades the user experience. So developers tend to avoid listening to these click events, but instead use the touchstart and touchend events to identify user’s taps. Frameworks usually provide a gesture library to simplify this, and extend it to other touch gestures like swipe, pinch, double-tap, etc. For example with Aria Templates: http://ariatemplates.com/mobile/kitchensink/#/gestures

But the click events are still fired, and they can lead to bad situations because even if not used, they can trigger changes on the UI. For example a click on a link will start navigation, a click on an input field will give it focus and will make the virtual keyboard to pop out.

The worst part is that the click event is fired on the DOM element which is located where the touchend event happened. So if the DOM has been changed in the meantime, then a click event is fired on the new element. This is a serious problem for websites made with a client-side templating framework.
Here is a sample which illustrates this use case:  http://instant.ariatemplates.com/anonymous/73cff696276a3fd79b6f/5a1657 or http://bit.ly/1sEqWCG

Preventing ghost clicks

Most mobile browsers offer ways to prevent or to mitigate ghost clicks, but for some of them, only javascript code can solve the problem.  Some possible workarounds:

  1. Calling preventDefault() on the touchstart event completely prevents the ghost click. It works in most browsers but has a big drawback: it is no longer possible to start scrolling the page from this DOM element.
  2. Call preventDefault() on the touchend event also completely prevents the ghost click. No drawbacks here at first sight, but it is only supported by a some browsers.
  3. If the page is not scalable thanks to proper meta tags (see Trick section at the end of the article), some browsers do not wait 300ms to fire the ghost clicks. They are still fired but faster, so the click event can reliably be used instead of a tap gesture.
  4. Clickbusters, i.e. javascript code that identifies ghost clicks and cancel them. It works but it has to be implemented carefully as cancelling too much clicks will make native HTML elements to not work correctly (e.g links, checkboxes, radio buttons).

The table below illustrates the discrepancies between mobile browsers when it comes to ghost click management. All tests were done with real devices using test pages available at http://mlaval.github.io/ghostclick/

 preventDefault()Ghost click timingGhost click coordinates
 touchstarttouchendScalable pageNot scalable pageScalable pageNot scalable page
Safari Mobile iOS 5.1.1YesYes370ms after end370ms after endtouchstarttouchstart
Safari Mobile iOS 6.1.3YesYes370ms after end370ms after endtouchstarttouchstart
Safari Mobile iOS 7.1.1YesYes370ms after end370ms after endtouchstarttouchstart
Android 2.3.7YesNo410ms after end410ms after endtouchstarttouchstart
Android 4.0.4YesNo300ms after end10ms after endtouchstarttouchstart
Android 4.1.2YesNo300ms after end300ms after endtouchstarttouchstart
Android 4.2.2YesNo300ms after start10ms after endtouchstarttouchend
IE10 Windows Phone 8NoNo310ms after end10ms after endtouchendtouchend
Blackberry 10YesYes260ms after end10ms after endtouchstarttouchstart
Chrome for iOSYesYes360ms after end360ms after endtouchstarttouchstart
Chrome for AndroidYesYes300ms after start10ms after endtouchstarttouchend
Firefox for AndroidYesNo300ms after end10ms after endtouchstarttouchend

Take away

From these results, three cases can be isolated depending on the browser and on the scalability of the page:

  • Ghost click is prevented when calling preventDefault() on the touchend event.
  • Fast ghost click mode (~10ms delay)
  • Slow ghost click mode (~300ms delay)

The only universal solution is a good clickbuster, which ideally should identify which of the 3 cases is the current one, and then apply the right fix. But such an identification is difficult before the application is actually used, so an approach for a good tap gesture would be:

  • Always call preventDefault() on the touchend event.
  • After a successful tap, cancel all click events in the same area during the next 500ms.
  • Analyze the first click bustings to identify if ghost clicks are prevented (case 1) or if ghost clicks are fast (case 2) is happening. If case 1, simply stop trying to cancel clicks. If case 2, only cancel clicks during 50ms after a tap.

Resources

To go further, some articles about ghost clicks:
http://updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away
http://www.appwards.nl/blog/2013/01/26/javascript-powered-webapps-and-click-versus-tap

And some clickbuster implementations:
https://github.com/ConradIrwin/zepto-ghostclick
https://developers.google.com/mobile/articles/fast_buttons
https://github.com/ftlabs/fastclick

Trick

To make a page not scalable, the following meta header must be added:
<meta name="viewport" content="width=device-width, user-scalable=no">
In addition in IE10, also add this CSS rule to remove the ghost click delay:
html {
-ms-touch-action: manipulation;
touch-action: manipulation;
}

posted on 2015-10-20 18:27  梦见世界 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lifeisshort/p/4895632.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值