Disable double-tap "zoom" option in browser on touch devices
Asked Answered
B

18

186

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.

Brander answered 16/5, 2012 at 8:13 Comment(2)
Though not for zoom, but here are some other essential ones - `-webkit-touch-callout: none; -webkit-text-size-adjust: none; -webkit-user-select: none;Hardball
It can maybe help (it did in my case) : But I noticed the double-tap problem only exists on divs, not on canvas.Insobriety
B
31

I just wanted to answer my question properly as some people do not read the comments below an answer. So here it is:

(function($) {
  $.fn.nodoubletapzoom = function() {
      $(this).bind('touchstart', function preventZoom(e) {
        var t2 = e.timeStamp
          , t1 = $(this).data('lastTouch') || t2
          , dt = t2 - t1
          , 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
        $(this).trigger('click').trigger('click');
      });
  };
})(jQuery);

I did not write this, i just modified it. I found the iOS-only version here: https://gist.github.com/2047491 (thanks Kablam)

Brander answered 6/6, 2012 at 8:17 Comment(8)
This doesn't seem to work, at least not on the SIII (w/ Android 4.0.4). I tried binding to document, body, window, *, no dice.Fishbein
Tryed me too, works on safari/ipad, android chrome but not with android default browserZebe
jquery isn't javascript it would be nice to have an example of how to do this without a libraryHeterogamy
Looking for a non-jquery version :-(Ferneferneau
again, jQuery is not javascript, and should not be encouraged, as it doesn't work well with sites based on more modern ideas like angular. read the questionHeterogamy
the question did not mention jQuery, jQuery is NOT a standard, it's totally outdated, and encourages writing illegible code, do you really want to continue this debate, i'm a bit tired of itHeterogamy
the answers here aren't just for the person who asked the question !, or else this site would not exist !Heterogamy
The correct answer is the CSS-only solution by Ross Allen belowStokeontrent
T
202

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;
}
<button>plain button</button>

<button class="disable-dbl-tap-zoom">button with disabled double-tap zoom</button>

<p>A <b>plain</b> paragraph. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.</p>

<p class="disable-dbl-tap-zoom">A paragraph <b>with disabled double-tap zoom</b>. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.</p>

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.

Tequila answered 10/11, 2018 at 4:35 Comment(11)
@SergoPasoevi, can you create an example that doesn't work? I am using this solution for iOS 12, and it is working for me.Tequila
I see the same problem as @SergoPasoevi, not working on iOS 12Thurible
Worked for me on iOS 12!Gabriel
what are the cons of wrapping your whole body with touch-action: manipulation?Nett
Doesn't work on latest iOS when double tapping an image.Musculature
I plan to track down why/how this does not work in iOS Safari after multiple reports of it no longer working. I will comment here again when I understand the issue and update the answer with what solves the issue.Tequila
It can maybe help (it did in my case) : But the double-tap problem only exists on divs, not on canvas.Insobriety
Works fine on iOS 14.6 (phone, not tablet, using Safari) when applied like this: input[type="button"]{ touch-action: manipulation; }. I can double tap elsewhere on the page and it'll either zoom or sometimes select, but when tapping on or even just near a button it'll always trigger the button and not do anything else. For future readers, perhaps you could update the edit on top to say that it works on buttons but potentially (since Adam Silver says it doesn't work for images) not for other elements?Womankind
For me, this worked in the current Safari in iOS 15. It disables touching, double touch, pan zoom, scrolling everywhere. It allows simple touching where necessary. Useful for "game mode" when you want to prevent unwanted gestures when quick touching the buttons etc. * { touch-action: none; pointer-events: none; } input, button, a { pointer-events: auto; }Alkyd
Does not work in 14.3 and 15.0 for certain elements. jsbin.com/sizavudima/edit?html,outputMechelle
Can I use... has it listed as working starting at iOS 13 which is the case for me on iOS 15. caniuse.com/?search=touch-action Thanks for the great answer!Pearly
S
77
<head>
<title>Site</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> 
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).

Shire answered 16/5, 2012 at 8:17 Comment(8)
That will disable ALL zoom functionality, unfortunately that was not my question. I want to disable only specified elements.Brander
Oi crap. I read it the other way around, fail's on me. Sorry!Shire
How about this solution? It's iOS only, but perhaps tweakable? : gist.github.com/2047491Shire
That's a nice little snippet. I hope someone can tell me how to get android devices in there too as I only have an iPad to test on. :PBrander
It was actually written by a fellow stackoverflow-er: https://mcmap.net/q/137293/-safari-ipad-prevent-zoom-on-double-tap :)Shire
@WouterKonecny If you remove the useragent check it should work on any device that supports the touchstart event. To detect those devices you can use a something like isEventSupportedHuberty
Apple now officially ignores this. github.com/w3c/html/issues/602Pogey
Does not work in 14.3 and 15.0 for certain elements. jsbin.com/sizavudima/edit?html,outputMechelle
O
50

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://mcmap.net/q/135342/-disable-double-tap-quot-zoom-quot-option-in-browser-on-touch-devices

Ovation answered 15/1, 2019 at 22:35 Comment(7)
This should be marked the answer. I tried putting it only on html and body but it didn't work in iOS 13.2. This works.Gasparo
This doesn't work on iOS 13 by itself, but in conjuction with this code it bocks tap to zoom for React app completely. document.getElementById('root').addEventListener('click', () => {})Nava
apple disabled tap to zoom on ios13, how can you say that it does not work on iOS13 ?Nett
Works for me - September 2020 on iOS SafariNumerical
@Numerical Does this work for you? I can't get it to work for me on iOS 14. Double tapping any element like divs / headings still cause a zoom on double tapEpigrammatize
@Epigrammatize Yep, still works a treat. When I remove that line in the OP, it zooms.Numerical
As of 2021, it does not seem to work on iOS Safari.Lamoureux
C
39

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.

Choose answered 26/2, 2015 at 20:40 Comment(9)
simple but great answer. no need to modify meta tags or etc.Arlinearlington
this disables clicks, I don't think it's a good solution sorryAlternation
@AlanSutherland, that's the point. If you read in the answer, it says that. The point is to over ride the click function. If you want to add the click function in like normal, simply add $('.no-zoom').click()Choose
you don't need JS to do that you can just set the CSS attribute pointer-events: noneAlternation
Thank you this worked perfectly for handling increment/decrement buttons without disabling zoom on the entire page.Hour
@AlanSutherland Just added * {pointer-events: none;} and it doesn't work on android 4.4.Simonsimona
The problem with this solution is if you're scrolling the page and your finger happens to be over the button, it thinks you clicked it.Glutamine
If I see this correctly, this might fail in certain situations where you need trusted events (for example clickin on sth which is triggering fullscreen or other experimentals, as the yneed trusted events which means TRIGGERED BY USER/OS)Behr
this works perfectly for navigation buttons or inc/dec btns etc. it will not disabled click because you add the this.click() line inside. it will although click the button if your scroll motion starts over it, but its not a problem for my case. thanks!Hermes
B
31

I just wanted to answer my question properly as some people do not read the comments below an answer. So here it is:

(function($) {
  $.fn.nodoubletapzoom = function() {
      $(this).bind('touchstart', function preventZoom(e) {
        var t2 = e.timeStamp
          , t1 = $(this).data('lastTouch') || t2
          , dt = t2 - t1
          , 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
        $(this).trigger('click').trigger('click');
      });
  };
})(jQuery);

I did not write this, i just modified it. I found the iOS-only version here: https://gist.github.com/2047491 (thanks Kablam)

Brander answered 6/6, 2012 at 8:17 Comment(8)
This doesn't seem to work, at least not on the SIII (w/ Android 4.0.4). I tried binding to document, body, window, *, no dice.Fishbein
Tryed me too, works on safari/ipad, android chrome but not with android default browserZebe
jquery isn't javascript it would be nice to have an example of how to do this without a libraryHeterogamy
Looking for a non-jquery version :-(Ferneferneau
again, jQuery is not javascript, and should not be encouraged, as it doesn't work well with sites based on more modern ideas like angular. read the questionHeterogamy
the question did not mention jQuery, jQuery is NOT a standard, it's totally outdated, and encourages writing illegible code, do you really want to continue this debate, i'm a bit tired of itHeterogamy
the answers here aren't just for the person who asked the question !, or else this site would not exist !Heterogamy
The correct answer is the CSS-only solution by Ross Allen belowStokeontrent
A
17

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); 
Ammadis answered 29/9, 2016 at 19:50 Comment(1)
brilliant. just wanted to mention that I needed to add an addEventListener in order to call this. myButton.addEventListener('touchstart', preventZoom);Lynd
S
12

You should set the css property touch-action to none as described in this other answer https://mcmap.net/q/137294/-unable-to-preventdefault-inside-passive-event-listener

.disable-doubletap-to-zoom {
    touch-action: none;
}
Solecism answered 20/12, 2017 at 6:44 Comment(4)
This works... but what if I want to disable zooming, but leave other touch events? I have a large table and this also disables scrolling.Marshall
If you only want to get rid of the double-tap zoom you should set the value to 'touch-action: manipulate;' This will still allow panning and pinch-zooming. Important Note: This also helps getting rid of the click delay browsers introduced to implement double-tap zoom. see developer.mozilla.org/en-US/docs/Web/CSS/touch-actionUball
On what HTML tag should this class be added?Untouched
I think you can just add it to any element that you don't want the use to zoom into. For example, in my case I didn't want the user to zoom into any part of my page, so I added it to the body tag.Miler
R
10
* {
    -ms-touch-action: manipulation;
    touch-action: manipulation;
}

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

Rapture answered 7/4, 2020 at 7:34 Comment(0)
M
8

Disable double tap zoom on mobile (2023 IOS Safari solution):

I found that using the meta tag method was not a viable solution for mobile safari browsers. Here is the solution that worked for me.

working solution:

.selector {
   touch-action: manipulation;
}

by simply adding a touch-action of manipulation all buttons with the following rule applied will not zoom on consecutive clicks of the button.

example website: calculator app

Marrow answered 22/12, 2022 at 22:9 Comment(2)
Amazing calculator app and love your about me page on Github!Roswell
Efficient solution.Closing
W
7

most of the coding above doesn't work unfortunately these simple lines will do it

document.addEventListener('dblclick', function(event) {
    event.preventDefault();
}, { passive: false });
Waist answered 8/3, 2022 at 11:1 Comment(2)
I can confirm that this was the only solution that worked in my case.Swingletree
simple and works!Repatriate
B
3

If you only want to prevent double click zoom across all devices, try setting the dblclick event listener of the button to preventDefault(). This worked for me!

edit: typo in 'dblclick'

const button = document.querySelector('#button');

button.addEventListener('dblclick', function(el) {
  el.preventDefault();
});
<button id="button"> No double click zoom here</button>
Babettebabeuf answered 15/6, 2021 at 13:55 Comment(0)
S
2

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().

Squish answered 24/8, 2016 at 19:54 Comment(1)
This worked for me. I was defining my own touchstart event on a button, and I wanted to disable the zoom function.Shericesheridan
E
1

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

Eelgrass answered 23/4, 2018 at 8:1 Comment(0)
B
0

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"
            }

 });
Baiss answered 17/3, 2017 at 15:22 Comment(0)
T
0

Here's a variation that currently, as of 2022, does the trick on most device versions; Android / iOS. Note that for example iOS 14+ zooms in on any text input fields that has a font-size of less than 1rem 16px, which also quite senior pros seem to have missed.

A vanilla javascript example - that can be improved further - for example with logic to allow normal behavior scenarios too - so for your experimentation.

document.getElementById('selectorid').addEventListener('touchend' || 'dblclick', event => { 
event.preventDefault();
event.stopImmediatePropagation();
    }, {
    passive: false
    });

Here's a more covering example for testing purposes to see if it achieves wished results. This one affects all the elements on the page inherited in the DOM.

 /* For testing purposes, overrides events that may trigger a "zoom"; note that this may cause other unexpected behavior */
 window.addEventListener('touchmove' || 'touchdowm' || 'touchend' || 'mousedown' || 'dblclick', event => {
            event.preventDefault();
            event.stopImmediatePropagation();


        }, {
            passive: false
        });

Here's some simple CSS, for overriding test purposes - try it out on the page and you may expect a remedy clue if form fields are what's bugging. Although the minimum size of 16px is actually quite wishfully intentional for accesibillity concerns. Note that the "!important" flag isn't considered good practice to manifest in a production deploy.

/* CSS to test prevention of zoom when interacting with input fields */
input[type=text] {
   font-size: 1rem !important; 
}
Tomikotomkiel answered 7/2, 2022 at 20:38 Comment(0)
D
-1

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">
Desert answered 16/8, 2017 at 13:58 Comment(0)
A
-3

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

Akilahakili answered 9/1, 2018 at 12:58 Comment(0)
S
-5

Here we go

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

Stovall answered 2/11, 2016 at 10:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.