disable viewport zooming iOS 10+ safari?

141,254

Solution 1

It's possible to prevent webpage scaling in safari on iOS 10, but it's going to involve more work on your part. I guess the argument is that a degree of difficulty should stop cargo-cult devs from dropping "user-scalable=no" into every viewport tag and making things needlessly difficult for vision-impaired users.

Still, I would like to see Apple change their implementation so that there is a simple (meta-tag) way to disable double-tap-to-zoom. Most of the difficulties relate to that interaction.

You can stop pinch-to-zoom with something like this:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, false);

Note that if any deeper targets call stopPropagation on the event, the event will not reach the document and the scaling behavior will not be prevented by this listener.

Disabling double-tap-to-zoom is similar. You disable any tap on the document occurring within 300 milliseconds of the prior tap:

var lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
  var now = (new Date()).getTime();
  if (now - lastTouchEnd <= 300) {
    event.preventDefault();
  }
  lastTouchEnd = now;
}, false);

If you don't set up your form elements right, focusing on an input will auto-zoom, and since you have mostly disabled manual zoom, it will now be almost impossible to unzoom. Make sure the input font size is >= 16px.

If you're trying to solve this in a WKWebView in a native app, the solution given above is viable, but this is a better solution: https://stackoverflow.com/a/31943976/661418. And as mentioned in other answers, in iOS 10 beta 6, Apple has now provided a flag to honor the meta tag.

Update May 2017: I replaced the old 'check touches length on touchstart' method of disabling pinch-zoom with a simpler 'check event.scale on touchmove' approach. Should be more reliable for everyone.

Solution 2

This is a new feature in iOS 10.

From the iOS 10 beta 1 release notes:

  • To improve accessibility on websites in Safari, users can now pinch-to-zoom even when a website sets user-scalable=no in the viewport.

I expect we're going to see a JS add-on soon to disable this in some way.

Solution 3

I've been able to fix this using the touch-action css property on individual elements. Try setting touch-action: manipulation; on elements that are commonly clicked on, like links or buttons.

Solution 4

The workaround that works in Mobile Safari at this time of writing, is to have the the third argument in addEventListener be { passive: false }, so the full workaround looks like this:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });

You may want to check if options are supported to remain backwards compatible.

Solution 5

It appears that this behavior is supposedly changed in the latest beta, which at the time of writing is beta 6.

From the release notes for iOS 10 Beta 6:

WKWebView now defaults to respecting user-scalable=no from a viewport. Clients of WKWebView can improve accessibility and allow users to pinch-to-zoom on all pages by setting the WKWebViewConfiguration property ignoresViewportScaleLimits to YES.

However, in my (very limited) testing, I can't yet confirm this to be the case.

Edit: verified, iOS 10 Beta 6 respects user-scalable=no by default for me.

Share:
141,254

Related videos on Youtube

Sam Su
Author by

Sam Su

too young too simple, sometimes naive

Updated on July 08, 2022

Comments

  • Sam Su
    Sam Su almost 2 years

    I've update my iPhone 6 plus to iOS 10 beta version and just found that in mobile safari, you can zoom any webpages by double tapping or pinching IGNORE the user-scalable=no code in the meta tag. I don't know whether it's a bug or feature. If it's considered as a feature, how do we disable viewport zooming iOS 10 safari ?


    updated on iOS 11/12 release, iOS 11 and iOS 12 safari still DO NOT respect the user-scalable=no meta tag.

    mobile github site on Safari

    • ErikE
      ErikE about 8 years
      An accessibility feature: Of note in Safari on iOS 10 twitter.com/thomasfuchs/status/742531231007559680/photo/1
    • dgatwood
      dgatwood over 7 years
      No, it isn't. It is bad practice for normal web content. For web apps, the default zoom behavior can completely ruin usability. For example, nobody wants to zoom in on a channel up button because they tapped it twice, nor zoom in on part of a video game because they tapped the jump button twice. There's a reason that this feature was added in the first place, and it makes no sense to break usability for everybody just because a few "web designers" don't know what they're doing. Go scream at the site designers and quit breaking the browser.
    • samrap
      samrap over 7 years
      Saying it's "bad practice" is an opinion and doesn't change the fact that Apple is insistent on taking web standards that the community spends months/years/decades getting implemented cross platform and taking a giant crap on them. Why should Apple dictate that web designers don't know what they're doing? Terrible argument.
    • William Isted
      William Isted over 7 years
      Personally, I think this stems from boilerplate code online where devs just copy and paste blindly without knowing what the purpose of the code is.
    • Ruben Martinez Jr.
      Ruben Martinez Jr. about 7 years
      Answer is simple, Apple: make disabling the meta tag a default-off accessibility setting. Those who need it, will have it, without punishing those who don't.
    • Piotr Kowalski
      Piotr Kowalski almost 7 years
      Have a look at my answer at the bottom of this page - my solution is a mix of other answers and my own invention.
    • Mick
      Mick almost 6 years
      Can someone confirm that none of the answers works on iOS 11 anymore?
    • TJR
      TJR over 5 years
      I can confirm that its not working in iOS 12 ... sadly.
    • pathfinder
      pathfinder over 5 years
      Apple shames the developer for not being accessible yet uses the tiniest font for everything. And if you use the accessibility features built into the os like making the font bigger it breaks the layout and sometimes even functionality. Such A-holes. I think it has more to do with trying to destroy web apps to force people into building apps they serve people through the apple store. Apple is the new Microsoft, remember IE6 - IE8.
  • Onza
    Onza almost 8 years
    This is bad... How can we make them change their mind?... why would you get UI designers then when your webapp breaks because of this.
  • Karlth
    Karlth almost 8 years
    Why would anything break? It is a viewport zoom, it is used so users can read webpages on small devices. It doesn't affect the UI.
  • wouterds
    wouterds almost 8 years
    @Onza: I don't think it's bad. I think it's good. Disabling pinch / zooming (default user behaviour) is considered bad, and a lot of mobile websites do it. The only acceptable user case would be a real web app that looks and feels like an app.
  • Onza
    Onza almost 8 years
    For some reason this causes that when you are clicking buttons it'll zoom, my buttons are the right size, I don't want them to zoom.
  • Paul Gerarts
    Paul Gerarts almost 8 years
    @Onza Buttons shouldn't trigger zoom unless you are double tapping them. Input fields do cause a zoom action when the keyboard and typing cursor appear.
  • Paul Gerarts
    Paul Gerarts almost 8 years
    @Onza If you have a button that requires multiple taps in short intervals you can use javascript to catch the touch events.
  • Zhenya
    Zhenya almost 8 years
    Bad.. I change viewport using js and block zoom only when some elements are selected on the website now it is broken due to this "decision". If someone decide to block it - there is a reason.
  • Sam Saffron
    Sam Saffron almost 8 years
    Note that touchstart hack is inconsistent... and if you manage to sidestep it you are stuck in a very uncomfortable state
  • JackCA
    JackCA almost 8 years
    I agree with @Joseph regarding the statement that Apple should reconsider/allow developers to bypass this for interactive mobile web experiences that don't even benefit from zooming in any capacity.
  • Sandeep
    Sandeep almost 8 years
    @Karlth it's very bed for a game developer
  • Karlth
    Karlth almost 8 years
    @Sandeep Why? (I'm a part time game developer). If the user decides to zoom into a part of the screen, why would that affect the game? It might affect his gameplay but not the code - it is just zooming handled by the device. It is just like taking a magnifying glass from a book reader - it doesn't change anything.
  • Felix
    Felix almost 8 years
    This is outdated. See Cellanes answer. iOS 10 now does support user-scalable=no
  • eljamz
    eljamz almost 8 years
    This works only if your app is a perfect fit... if you do have scrollable content it doesn't works... still nice hack for some scenarios.
  • Gags
    Gags almost 8 years
    This even disables scroll on website.. BAD
  • lifwanian
    lifwanian almost 8 years
    10.0.1 here. Does not respect it. What is with Apple getting rid of features that everyone needs..
  • Fabio Poloni
    Fabio Poloni almost 8 years
    This refers to WKWebView not to Safari. Source: One of our map apps broke and we have no idea how to fix it.
  • webkit
    webkit almost 8 years
    I have IOS 10.0.2, user-scalable=no does not disable zooming anymore on our website... Our main issue with zooming is with our fixed side menu.. It just breaks the layout.. Any ideas or solutions on this? I understand zooming is good for accessibility, we made zooming available on specific parts of our site using js events (hammer) & css.. I don't see why a rule has to be imposed on everyone, seems like the PC Police is starting to take over our dev world as well?!
  • Cellane
    Cellane almost 8 years
    Aha! Apologies, I came here when searching for solution for the same bug/feature in WKWebView and kind of assumed that the original question asked about WKWebView when writing my answer. So I suppose that during one of the first beta versions, Apple changed the behavior of both WKWebView and mobile Safari, then in beta 6, they reverted the behavior of WKWebView but kept it for the mobile Safari.
  • Timo Kähkönen
    Timo Kähkönen over 7 years
    Eg. full screen mapping apps, there is a zoom feature hard coded in the mapping application (Google Maps JS, Leaflet etc.). Google advices to add a meta tag <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> and if browser doesn't respect the meta tag, it is very bad browser design. The other this like very bad design is back/forward action by sliding, which cannot be prevented in iOS 9/10. It breaks severely dragging actions inside web application.
  • Aidan Hakimian
    Aidan Hakimian over 7 years
    10.0.2 does not respect user-scalable=no. I'm not sure why they would ever undo this, only to bring it back, only to remove it again.
  • Chihying Wu
    Chihying Wu over 7 years
    @eljamz thanks for let me know and yes..my app is perfect fit on screen.
  • Chihying Wu
    Chihying Wu over 7 years
    @Gags I didn't test the scroll function yet, thanks for let me know.
  • Conan
    Conan over 7 years
    I've also been trying to solve this problem when working with hammer.js, and can confirm that I could prevent the viewport zoom by adding a .preventDefault to all the hammer gesture handlers. I'm using swipe/pinch/pan/tap together, i've added it to all the handlers, i don't know whether there's a specific one that's doing the job.
  • Nebula
    Nebula over 7 years
    "The only acceptable user case would be a real web app that looks and feels like an app." - and this is, like you said, a real, acceptable use case, that isn't that rare..
  • Reado
    Reado over 7 years
    Both hacks do not work with iOS 10.1.1 when double-tapping or pinch-zooming an image. They prevent these actions happening on text, but images seem to be excluded?
  • Paolo
    Paolo over 7 years
    If user start dragging with one finger then put a second finger on the screen will be able to pinch-zoom. You can disable both zoom and scroll with a preventDefault on touchmove. You can't (completely) disable zoom without disabling scroll.
  • Sam Su
    Sam Su over 7 years
    how about pinching?
  • mariomc
    mariomc over 7 years
    Unfortunately, pinch to zoom is not covered by this solution. For that, we used the solution proposed in: stackoverflow.com/a/39594334/374196
  • robocat
    robocat over 7 years
    Doesn't work for me. I am using 10.2.1 Beta 4 on an iPod Touch using this test page and double tapping any of the grey squares zooms: jsbin.com/kamuta/quiet
  • Ryan
    Ryan over 7 years
    Wow, this part (I'll paste here) was SUPER helpful to me. I haven't seen this mentioned by anyone else ANYWHERE on the internet. It took me hours to fix this problem. I'm really disappointed in Apple's UX design choices about this, where forms auto-zoom-in but then don't zoom back out. If you don't set up your form elements right, focusing on an input will auto-zoom, and since you have mostly disabled manual zoom, it will now be almost impossible to unzoom. Make sure the input font size is >= 16px.
  • Fasani
    Fasani over 7 years
    I have this on a span in a react app and it does not work.
  • Moos
    Moos over 7 years
    "manipulation" doesn't prevent pinch zoom, only double-tap zoom.
  • robocat
    robocat over 7 years
    For "apps" we should be able to prevent double-tap to zoom. Double tap occurs unintentionally for normal users e.g. tapping a + button twice, tapping a list item twice. Note that the double-tap zoom also re-introduces the 300ms delay between touchend and click (fixed in iOS9 and broken again in iOS10 - a non-zoomable page in iOS9 has zero delay and iOS10 adds that delay back in again - arrgh!). Accessability is fine if pinch to zoom allowed. Focusing an input with a small font size causing automatic zoom is also sensible for accessability. Double-tap zoom breaks accessability for tremors.
  • Jason FB
    Jason FB over 7 years
    I have an web app that I want to look & feel like a "real app" -- and this Safari ignore-ence (pun intended) completely messes the UX up. What a dumb move on Safari's part.
  • Andrzej Dąbrowski
    Andrzej Dąbrowski about 7 years
    @webkit On of the reason it breaks layout is because after zooming in window.innerWidth and window.innerHeight change (while document width / height remain the same) and fixed elements got repositioned to new window size. This occured till iOS 10.2, in new update iOS 10.3, this "feature" is dropped and fixed elements are aligned to document, not zoom-adjusted window size. Still we need to take care of touch events (e.g. intercepted by hammer) though. It's probably best to just disable all swipe / pan / pinch events (like galleries) when window is zoomed-in to allow user pan zoomed-in site.
  • Ramesh kumar
    Ramesh kumar about 7 years
    Thanks, It is helpful for me.
  • Dirk Boer
    Dirk Boer about 7 years
    They should have made this an option in the accessibility menu, so it's still an option but for the other 99% of the users not the default behaviour.
  • Paul Gerarts
    Paul Gerarts about 7 years
    @DirkBoer I have to disagree with you. Apple is trying to make their products appealing for everyone. This includes people with poor-sight, a huge portion of them are the elderly. Those people rely on the it-just-works-out-of-the-box'ness of the devices. These are not people that are going to find the "allow me to zoom everywhere" feature. People with niche disabilities know to search for help-me features, those are the ones you find in Accessibility. - From Apple's perspective, I understand why they did it this way. - Is what I'm trying to say.
  • Dirk Boer
    Dirk Boer about 7 years
    Hi Paul, I understand what you're saying. I think it's rather arbitrary though, because all 'navtive' apps won't zoom in anyway if you don't go to the accesibility menu explicitly.
  • Paul Gerarts
    Paul Gerarts about 7 years
    @DirkBoer well-implemented apps scale with the system-font size slider if I'm not mistaken. But again, then why not just decrease the perceived screen width in the browser if we increase the font-size (effectively scaling-up the website's UI). Responsive sites should be able to handle abuse like this. That seems like a nice solution to me anyway.
  • Paul Gerarts
    Paul Gerarts about 7 years
    @DirkBoer System-font size slider is very easy to find since it is (almost) accessible from the main settings page. Pinching is also something we expect to work in the browser, because it usually does. So the fact that it would suddenly not work could be considered confusing behaviour.
  • jamesSampica
    jamesSampica almost 7 years
    Unfortunately this only works when your page is a perfect fit, not when you have scrollable content
  • Jeff McMahan
    Jeff McMahan almost 7 years
    Hmm. This works fine with scrollable content, in my experience (iOS 10.3).
  • Guy Sopher
    Guy Sopher almost 7 years
    This should be the accepted answer. you can use touch-action: none; to control all the gestures yourself.
  • pilar1347
    pilar1347 almost 7 years
    This is what finally disabled the double-tap zoom for me. Although, I found with the 300ms span, a slower double-tap would still register. Increasing the gap to 500ms worked for me. Thanks!
  • Larry
    Larry over 6 years
    this is great - disabling double-tap zooming while leaving pinch zooming, which SHOULD be considered a gesture - double tapping should not. 1 dog is a dog. 1 dog + 1 dog does not a space shuttle make. It makes 2 dogs, and they do things that you'd expect 2 dogs to do. I have never expected 2 dogs to be a space shuttle. Never.
  • Stewart
    Stewart about 6 years
    Can you point me to the MDN doc that describes event.scale. I'm using typescript and I can't resolve the event type. I have found developer.mozilla.org/en-US/docs/Web/API/GestureEvent but it's marked as a non-standard API.
  • Joseph
    Joseph about 6 years
    @Stewart Yeah, it's iOS-specific. But so is this question.
  • Mathieu R.
    Mathieu R. about 6 years
    This works on my iPad emulator which is running iOS 11.2. On my real iPad running iOS 11.3 it doesn't work. I added a console.log to make sure the events are fired and so they appear in the console. It is something to do with iOS 11.3 ? Or with real devices ?
  • Josh Gallagher
    Josh Gallagher about 6 years
    @MathieuR. It is an iOS 11.3 issue. It can be rectified by using one of the addEventListener based answers and passing { passive: false } as the options parameter instead of false. However, for backward compatibility you need to pass false unless the passive option field is supported. See developer.mozilla.org/en-US/docs/Web/API/EventTarget/…
  • Mick
    Mick almost 6 years
    @JoshGallagher Could you provide a working example? On iOS11 none of the answers is working for me.
  • Mick
    Mick almost 6 years
    Why don't you use gesturestart instead touchmove with if clause? You would safe performance by not having a if clause, or is there any reason to do so?
  • Mick
    Mick almost 6 years
    The only problem is pinch zoom works while scrolling: To reproduce scroll slightly with one finger and then pinch with the other -> Zoom works and preventDefault() has no effect.
  • Nick Bilyk
    Nick Bilyk over 5 years
    Thank you. I spent hours looking for something that actually worked. This combined with making my 3d canvas fixed position solved it!
  • Nick Bilyk
    Nick Bilyk over 5 years
    My use case is also a full page 3d scene with custom pinch controls. I would have been sunk if there wasn't a workaround to Apple explicitly ignoring the user-scale: no meta.
  • Patrick DaVader
    Patrick DaVader over 5 years
    Anyone tried this on iOS 12? I added the above code and it is doing nothing for my webapp. Still able to zoom in this stupid Safari. My meta viewport tag looks like this btw: <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">.
  • humanityANDpeace
    humanityANDpeace over 5 years
    @GuySopher iOS does not provide touch-action: none only manipulatoin, which leaves the pinch-zoom problem as it is.
  • Jamie Birch
    Jamie Birch over 5 years
    @PatrickDaVader Yep, can't find any working solution for iOS 12 Safari. Getting seasick from all the incessant zooming.
  • TJR
    TJR over 5 years
    It seems that this isnt working in iOS 12 anymore. Any idea how to make this work for iOS 12?
  • pathfinder
    pathfinder over 5 years
    I am certain it would have been a lot less code for apple to just add a switch in safari or accessibility settings that overrides the user-scalable meta tag, which would much more truly improve accessibility. They should also have a switch to turn off zoom and double-tap to zoom for folks who have parkinsons. We should all be shaming apple for using accessibility as a reason to push more people into apps only "accessible" in their web store. They don't really give a rats @ss about anything but profit.
  • Alexey Grinko
    Alexey Grinko over 5 years
    Note that if you ever want to remove this event listener (e.g. you disable default behavior only for a temporal interaction), you also have to pass false (or { capture: true }) as the last argument to removeEventListener: document.removeEventListener('touchmove', yourFunction, false). Struggled with this for a bit myself as page stopped scaling and scrolling forever after one interaction
  • Jamie Burton
    Jamie Burton about 5 years
    Setting the font size to 16px was the fix for me
  • Michael Camden
    Michael Camden almost 5 years
    The 'gesturestart' -> preventDefault works for me at time of writing on iOS 12,2
  • Sterling Bourne
    Sterling Bourne almost 5 years
    This one works in iOS 13. My <meta> tags include: <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" /> and <meta name="HandheldFriendly" content="true">
  • LandP
    LandP over 4 years
    This works in iOS 12.3.1. My <meta> tag is: <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  • Hillcow
    Hillcow over 4 years
    @SterlingBourne Copied your setup. Does work, but only like 90% of the time. Not sure why not all the time.
  • Sterling Bourne
    Sterling Bourne over 4 years
    @Hillcow: I ended up needing to use a Node Module to 100% get this to work: npmjs.com/package/body-scroll-lock
  • wayofthefuture
    wayofthefuture over 4 years
    iOS 13 change false to {passive: false}
  • wayofthefuture
    wayofthefuture over 4 years
    iOS 13 change false to {passive: false}
  • Gene Black
    Gene Black over 4 years
    @SterlingBourne response worked for me! Thanks. He should post it as an answer rather than a comment so it can be voted <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" /> and <meta name="HandheldFriendly" content="true">
  • TGR
    TGR about 4 years
    I tried this, it did prevent pinch zooming, however it disables touch scrolling of the viewport so you cannot scroll the page up and down anymore.
  • JeanPaul A.
    JeanPaul A. almost 4 years
    Why does this work 90% of the time? I tried it on mine and didn't work :(
  • Husky931
    Husky931 over 3 years
    use touch-action: pan-x pan-y, fixes it.
  • Sébastien Gicquel
    Sébastien Gicquel over 3 years
    Tested on iOS 14.4 : it disables touch scrolling of the viewport so you cannot scroll the page up and down anymore.
  • David Bradbury
    David Bradbury about 3 years
    Life-saver - This is the only solution that works for me as of iOS 14.4.2 that still allows for multi-touch being registered - My use-case being a web game that uses joystick controls for mobile.
  • MichaelG
    MichaelG about 3 years
    It's bad for map applications where pinch zooming is important.
  • kubi
    kubi almost 3 years
    The event.scale bit works for me on iOS, but it prevents any & all panning on Android/Chrome v91. To make it work across these platforms I had to add if (('scale' in event) && event.scale !== 1) { ...
  • kosmosan
    kosmosan almost 3 years
    Best answer nowadays. It works perfectly.
  • Geetanshu Gulati
    Geetanshu Gulati almost 3 years
    Its' not working on scrollable element but working on non-scrollable element, what is scaleable solution to avoid this issue for scrollable element
  • Michael
    Michael over 2 years
    Flawless on iOS 15