Proper use of touch events for smooth interactions

Easy solution to achieve smooth and instant interactions on touch devices

The Problem

The problem with using the events mouseenter mouseleave and click on touch devices, is that they don't get triggered right: if you use mouseenter and mouseleave with click, you have to double touch the items (the first touch triggers mouseenter and the second triggers click) and the mouseleave doesn't get executed when clicking links.

A non optimal solution is to add touchstart to the click event; this way you don't need to double touch, but the code gets executed two times, and the problem of triggering mouseleave is still there.

The Partial Solution

The best solution I've found after many tries is to use on touch devices the events touchstart and touchend instead of mouseenter and mouseleave.

// we use touchstart and touchend events
var enterEvent = "touchstart";
var leaveEvent = "touchend";
if(!("ontouchstart" in window) && !(navigator.maxTouchPoints > 0) && !(navigator.msMaxTouchPoints > 0)){
    // if no touch we use mouseenter and mouseleave events
    enterEvent = "mouseenter";
    leaveEvent = "mouseleave";
}

$(".button").on(enterEvent, function(e){
    // code here
});
$(".button").on(leaveEvent, function(e){
    // code here
});

With the code above:

  • You don't have to double touch to trigger the click event, and the code get executed one time
  • The click event doesn't have 300ms click delay on touch
  • You have perfect behaviours and animations on touch, because the touchstart triggers when you start touching, and the touchend triggers when you end touching
  • The touchstart and touchend animation syncs with the css animations on :active

The Final Solution

The partial solution, perfect for buttons and links, is not suitable for items that takes much space of the display, since scrolling with the touch will trigger the touchstart and will make scrolling slower on mobile and pads: so on this occurrence on touch devices it's better to use mousedown and mouseup instead of touchstart and touchend.

// we use touchstart and touchend events on buttons
var enterEvent = "touchstart";
var leaveEvent = "touchend";
// we use mousedown and mouseup events on big items
var enterBigEvent = "mousedown";
var leaveBigEvent = "mouseup";
if(!("ontouchstart" in window) && !(navigator.maxTouchPoints > 0) && !(navigator.msMaxTouchPoints > 0)){
    // if no touch we use mouseenter and mouseleave events on buttons and big items
    enterEvent = enterBigEvent = "mouseenter";
    leaveEvent = leaveBigEvent = "mouseleave";
}

$(".button").on(enterEvent, function(e){
    // code here
});
$(".button").on(leaveEvent, function(e){
    // code here
});

$(".big-item").on(enterBigEvent, function(e){
    // code here
});
$(".big-item").on(leaveBigEvent, function(e){
    // code here
});