[html] Disable double-tap "zoom" option in browser on touch devices

I want to disable the double-tap zoom functionality on specified elements in the browser (on touch devices), without disabling all the zoom functionality.

For example: One element can be tapped multiple times for something to happen. This works fine on desktop browsers (as expected), but on touch device browsers, it will zoom in.

This question is related to html browser touch zooming

The answer is


I assume that I do have a <div> input container area with text, sliders and buttons in it, and want to inhibit accidental double-taps in that <div>. The following does not inhibit zooming on the input area, and it does not relate to double-tap and zooming outside my <div> area. There are variations depending on the browser app.

I just tried it.

(1) For Safari on iOS, and Chrome on Android, and is the preferred method. Works except for Internet app on Samsung, where it disables double-taps not on the full <div>, but at least on elements that handle taps. It returns return false, with exception on text and range inputs.

$('selector of <div> input area').on('touchend',disabledoubletap);

function disabledoubletap(ev) {

    var preventok=$(ev.target).is('input[type=text],input[type=range]');

    if(preventok==false) return false; 
}

(2) Optionally for built-in Internet app on Android (5.1, Samsung), inhibits double-taps on the <div>, but inhibits zooming on the <div>:

$('selector of <div> input area').on('touchstart touchend',disabledoubletap);

(3) For Chrome on Android 5.1, disables double-tap at all, does not inhibit zooming, and does nothing about double-tap in the other browsers. The double-tap-inhibiting of the <meta name="viewport" ...> is irritating, because <meta name="viewport" ...> seems good practice.

<meta name="viewport" content="width=device-width, initial-scale=1, 
          maximum-scale=5, user-scalable=yes">

This will prevent double tap zoom on elements in 'body' this can be changed to any other selector

$('body').bind('touchstart', function preventZoom(e){
            var t2 = e.timeStamp;
            var t1 = $(this).data('lastTouch') || t2;
            var dt = t2 - t1;
            var fingers = e.originalEvent.touches.length;
            $(this).data('lastTouch', t2);
            if (!dt || dt > 500 || fingers > 1){
                return; // not double-tap
            }
            e.preventDefault(); // double tap - prevent the zoom
            // also synthesize click events we just swallowed up
            $(e.target).trigger('click');

});

But this also prevented my click event from triggering when clicked multiple times so i had to bind a another event to trigger the events on multiple clicks

$('.selector').bind('touchstart click', preventZoom(e) {    
    e.stopPropagation(); //stops propagation
    if(e.type == "touchstart") {
      // Handle touchstart event.
    } else if(e.type == "click") {
      // Handle click event.
    }
});

On touchstart i added the code to prevent the zoom and trigger a click.

$('.selector').bind('touchstart, click', function preventZoom(e){
            e.stopPropagation(); //stops propagation
            if(e.type == "touchstart") {
                // Handle touchstart event.
                var t2 = e.timeStamp;
                var t1 = $(this).data('lastTouch') || t2;
                var dt = t2 - t1;
                var fingers = e.originalEvent.touches.length;
                $(this).data('lastTouch', t2);


                if (!dt || dt > 500 || fingers > 1){
                    return; // not double-tap
                }

                e.preventDefault(); // double tap - prevent the zoom
                // also synthesize click events we just swallowed up
                $(e.target).trigger('click');

            } else if(e.type == "click") {
                // Handle click event.
               "Put your events for click and touchstart here"
            }

 });

I know this may be old, but I found a solution that worked perfectly for me. No need for crazy meta tags and stopping content zooming.

I'm not 100% sure how cross-device it is, but it worked exactly how I wanted to.

$('.no-zoom').bind('touchend', function(e) {
  e.preventDefault();
  // Add your code here. 
  $(this).click();
  // This line still calls the standard click event, in case the user needs to interact with the element that is being clicked on, but still avoids zooming in cases of double clicking.
})

This will simply disable the normal tapping function, and then call a standard click event again. This prevents the mobile device from zooming, but otherwise functions as normal.

EDIT: This has now been time-tested and running in a couple live apps. Seems to be 100% cross-browser and platform. The above code should work as a copy-paste solution for most cases, unless you want custom behavior before the click event.


Using CSS touch-events: none Completly takes out all the touch events. Just leaving this here in case someone also has this problems, took me 2 hours to find this solution and it's only one line of css. https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action


You should set the css property touch-action to none as described in this other answer https://stackoverflow.com/a/42288386/1128216

.disable-doubletap-to-zoom {
    touch-action: none;
}

If there is anyone like me who is experiencing this issue using Vue.js, simply adding .prevent will do the trick: @click.prevent="someAction"


* {
    -ms-touch-action: manipulation;
    touch-action: manipulation;
}

Disable double tap to zoom on touch screens. Internet explorer included.


Simple prevent the default behavior of click, dblclick or touchend events will disable the zoom functionality.

If you have already a callback on one of this events just call a event.preventDefault().


Note (as of 2020-08-04): this solution does not appear to work in iOS Safari v12+. I will update this answer and delete this note once I find a clear solution that covers iOS Safari.

CSS-only solution

Add touch-action: manipulation to any element on which you want to disable double tap zoom, like with the following disable-dbl-tap-zoom class:

.disable-dbl-tap-zoom {
  touch-action: manipulation;
}

From the touch-action docs (emphasis mine):

manipulation

Enable panning and pinch zoom gestures, but disable additional non-standard gestures such as double-tap to zoom.

This value works on Android and on iOS.


CSS to disable double-tap zoom globally (on any element):

  * {
      touch-action: manipulation;
  }

manipulation

Enable panning and pinch zoom gestures, but disable additional non-standard gestures such as double-tap to zoom.

Thanks Ross, my answer extends his: https://stackoverflow.com/a/53236027/9986657


Here we go

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


If you need a version that works without jQuery, I modified Wouter Konecny's answer (which was also created by modifying this gist by Johan Sundström) to use vanilla JavaScript.

function preventZoom(e) {
  var t2 = e.timeStamp;
  var t1 = e.currentTarget.dataset.lastTouch || t2;
  var dt = t2 - t1;
  var fingers = e.touches.length;
  e.currentTarget.dataset.lastTouch = t2;

  if (!dt || dt > 500 || fingers > 1) return; // not double-tap

  e.preventDefault();
  e.target.click();
}

Then add an event handler on touchstart that calls this function:

myButton.addEventListener('touchstart', preventZoom); 

<head>
<title>Site</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> 
etc...
</head>

I've used that very recently and it works fine on iPad. Haven't tested on Android or other devices (because the website will be displayed on iPad only).


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to browser

How to force reloading a page when using browser back button? How do we download a blob url video How to prevent a browser from storing passwords How to Identify Microsoft Edge browser via CSS? Edit and replay XHR chrome/firefox etc? Communication between tabs or windows How do I render a Word document (.doc, .docx) in the browser using JavaScript? "Proxy server connection failed" in google chrome Chrome - ERR_CACHE_MISS How to check View Source in Mobile Browsers (Both Android && Feature Phone)

Examples related to touch

Consider marking event handler as 'passive' to make the page more responsive Touch move getting stuck Ignored attempt to cancel a touchmove How to remove/ignore :hover css style on touch devices Fix CSS hover on iPhone/iPad/iPod How to prevent sticky hover effects for buttons on touch devices Draw in Canvas by finger, Android Disable scrolling when touch moving certain element How to implement swipe gestures for mobile devices? Prevent Android activity dialog from closing on outside touch Media query to detect if device is touchscreen

Examples related to zooming

IntelliJ how to zoom in / out Disable double-tap "zoom" option in browser on touch devices How to implement zoom effect for image view in android? android pinch zoom enable/disable zoom in Android WebView How can I zoom an HTML element in Firefox and Opera? Disable Auto Zoom in Input "Text" tag - Safari on iPhone How can I get zoom functionality for images? How to detect page zoom level in all modern browsers? Changing the browser zoom level