Prevent zoom cross-browser

100,038

Solution 1

I haven't really found an "authoritative" answer, meaning a clear statement from browser developers. However, all answers to similar questions I've found (like this one or that one) suggest the same thing - the browser's zoom feature exists for the benefit of the users and some browsers (like Firefox) simply don't allow you, as a website creator, to take this option away from them.


This documentation might shed some light into why allowing authors to disable zoom might be a good idea on mobile devices, but not on desktops.

In short, you might need to prevent mobile devices from initially auto-zooming your website, if you know their calculated auto-zoom will be inappropriate. On desktops, there is no auto-zoom, so when users come to your website, they see it exactly as it was meant to be seen. If they then decide they need to zoom the page, there's no good reason to let you prevent them from doing so.


As for the solutions you've listed:

Solution 2

You can disable zoom in browser when using Ctrl + + or Ctrl + - or Ctrl + mouse wheel up or Ctrl + mouse wheel down with this code.

$(document).keydown(function(event) {
if (event.ctrlKey==true && (event.which == '61' || event.which == '107' || event.which == '173' || event.which == '109'  || event.which == '187'  || event.which == '189'  ) ) {
        event.preventDefault();
     }
    // 107 Num Key  +
    // 109 Num Key  -
    // 173 Min Key  hyphen/underscore key
    // 61 Plus key  +/= key
});

$(window).bind('mousewheel DOMMouseScroll', function (event) {
       if (event.ctrlKey == true) {
       event.preventDefault();
       }
});

Check a demo here: JSFiddle.

Solution 3

I think what you can do is, listen to browser zoom event(ctrl + "+") and then check for window.devicePixelRatio.

Then accordingly, apply HTML5 scale transformation on the body element to scale down by the same ratio. So, basically you cannot prevent the functionality but you can apply negative effect with the same magnitude.

POC Code:

 <body style="position: absolute;margin: 0px;">
        <div style="width: 300px; height: 200px; border: 1px solid black;">
            Something is written here
        </div>
        <script>
            var keyIncrease = [17, 61];
            var keyDecrease = [17, 173];
            var keyDefault = [17, 48];
            var listenMultiKeypress = function(keys, callback){
                var keyOn = [];
                for(var i=0; i<keys.length; i++){
                    keyOn[i] = false;
                }
                addEventListener('keydown', function(e){
                    var keyCode = e.which;
                    console.log(keyCode);
                    var idx = keys.indexOf(keyCode);
                    if(idx!=-1){
                        keyOn[idx] = true;
                    }
                    console.log(keyOn);
                    for(var i=0; i<keyOn.length; i++){
                        if(!keyOn[i]){
                            return;
                        }
                    }
                    setTimeout(callback, 100);
                });
                addEventListener('keyup', function(e){
                    var keyCode = e.which;
                    var idx = keys.indexOf(keyCode);
                    if(idx!=-1){
                        keyOn[idx] = false;
                    }
                    console.log(keyOn);
                });
            };
            var previousScale = 1;
            var previousDevicePixelRatio;
            var neutralizeZoom = function(){
                //alert('caught');
                var scale = 1/window.devicePixelRatio;

                document.body.style.transform = 'scale('+(1/previousScale)+')';
                document.body.style.transform = 'scale('+scale+')';
                var widthDiff = parseInt(getComputedStyle(window.document.body).width)*(scale-1);
                var heightDiff = parseInt(getComputedStyle(window.document.body).height)*(scale-1);
                document.body.style.left = widthDiff/2 + 'px';
                document.body.style.top = heightDiff/2 + 'px';
                previousScale = scale;
            };

            listenMultiKeypress(keyIncrease, neutralizeZoom);
            listenMultiKeypress(keyDecrease, neutralizeZoom);
            listenMultiKeypress(keyDefault, neutralizeZoom);
            neutralizeZoom();
        </script>
    </body>
</html>

Solution 4

Insert the following into your HTML:

For Mobiles: Insert between the '< head>...< /head>' tag.

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">

For Desktops across-Browsers: Insert just after start '< body>...' tag.

<script>
  document.body.addEventListener("wheel", e=>{
    if(e.ctrlKey)
      e.preventDefault();//prevent zoom
  });
</script>

Solution 5

So, as has been mentioned, that really isn't possible. However, there are some ways you can still be smart about it.

Three of the five major browsers all allow you to see the zoom level of the browser, furthermore, should the browser be zoomed a window.onresize event is fired.

IE:      event.view.devicePixelRatio           OR window.view.devicePixelRatio
Chrome:  event.currentTarget.devicePixelRatio  OR window.devicePixelRatio
Firefox: event.originalTarget.devicePixelRatio OR window.devicePixelRatio
Safari:  /* Not possible */
Opera:   /* Not possible */

I think the stuff after OR works based on something I noticed as I was messing around. The first ones I know work in at least the latest version of each one. Note that Safari and Opera both have the devicePixelRatio, however both never change. It's always just 1.

The above is your easy way if you don't care that much. If you do, then you could try out the detect-zoom script, which I came across while looking for solutions to Safari and Opera.

So what you can now do is get the zoom level, and then offset your zoom to where it doesn't do anything. So if I force my browser to 50% zoom, you just go to 200%. Thus, no change. Of course it will be a bit more complicated, you'll have to store the last browser zoom, the new browser zoom, and do some slightly more complicated math, but based on what you already have, that should be a breeze.

Another idea might be to just listen for a resize event, and calculate based off the new visible size, but that might cause issues if the window is just resized. I think the above is going to be your best option, with perhaps a fallback alert to warn the user not to zoom if necessary.

Share:
100,038
Basj
Author by

Basj

I work on R&amp;D involving Python, maths, machine learning, deep learning, data science, product design, and MacGyver solutions to complex problems. I love prototyping, building proofs-of-concept. For consulting/freelancing inquiries : [email protected]

Updated on December 08, 2021

Comments

  • Basj
    Basj over 2 years

    For a map-like tool, I would like to disable the browser zooming feature. (I know that this is generally a bad idea, but for some specific website, it is needed).

    I did it successfully by listening the keyboard shortcut CTRL + / CTRL - and adding e.preventDefault(), etc. But this doesn't prevent from changing the zoom from the browser's Zoom menu.

    I tried:

    • with CSS: zoom: reset; It works for Chrome (see this page for a working example) but it doesn't work at all on Firefox.

    • in various questions/answers, I also found

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

      but this seems to work for mobile only.


    How to prevent zooming cross-browser ?

  • stackErr
    stackErr over 9 years
    This is probably the best way to go about and covers all scenarios. And the detect-zoom script does not work with new versions of Chrome and Firefox. But as stated, Safari and Opera are supported.
  • hon2a
    hon2a over 9 years
    The app you've linked in a question comment is all about zoom, which makes my answer less relevant to your particular situation. Still, it may be helpful in general, I guess.
  • Basj
    Basj over 9 years
    Do you think @David it could be possible to update this HTML page gget.it/vtn8i8rb/NFB92BF.HTML, so that zooming is disabled, as much as we can (of course, it won't work on every browser) with the techniques you propose here? Currently on this page only CTRL + / CTRL - is disabled
  • David
    David over 9 years
    @Basj, the methods mentioned in this post are reliant on your design. The properties are read only, so the best you're going to be able to do is counteract them. E.g. if you're at 223% zoom, and the user changes it to 150% zoom, you'd then read that, and go to 1.486% zoom on your code. (If I'm doing the math right: 223/150). If the user changes again, then you'd pretent 150% is 100% and do the math based off of that. Something like the page you've given is straight text, so that doesn't work. Furthermore, you wouldn't want to prevent zoom on that type of page.
  • Shanu Shaji
    Shanu Shaji almost 9 years
    Ctrl and + make it zoom
  • Vijay Dhanvai
    Vijay Dhanvai almost 9 years
    Yes it Zoom in chrome browser, Now check again i have update condition.
  • PioneerMan
    PioneerMan almost 8 years
    I pasted your code into jsfiddle.net and I can still zoom on a mac using Command +
  • B. Colin Tim
    B. Colin Tim over 7 years
    PS: You can do this with CSS for webkit browsers like this:
  • carefulnow1
    carefulnow1 about 7 years
    Control + Numpad +/- ?
  • Andrii Gordiichuk
    Andrii Gordiichuk over 6 years
    @NestMan, I think you forgot put }); in the end.
  • Admin
    Admin about 6 years
    This prevents it from zooming, great job, but if you really try to scroll zoom it still zooms on chrome.
  • 10 Replies
    10 Replies almost 4 years
    This no longer works as of 2020 in any of the browsers I tested
  • Maxim Georgievskiy
    Maxim Georgievskiy over 3 years
    On my macbook, I pinch out on trackpad (moving two fingers on trackpad from each other at the same time) - browser calls "mousewheel" event and the script does not work, because crtlKey is not pressed (neither Cmd key).
  • Jian Zhong
    Jian Zhong over 2 years
    Check my answer follow, just add {passive: false} when addEventerListener window.addEventListener("wheel", handleWheel, {passive: false}); stackoverflow.com/questions/27116221/prevent-zoom-cross-brow‌​ser/…
  • hon2a
    hon2a over 2 years
    Please read the question in full. It's not about reacting to mouse wheel events.
  • Jian Zhong
    Jian Zhong over 2 years
    Yes, you are right. Some people said it does not work on modern bowser any more. And i solve the zooming by wheel event a few days ago. Maybe it is helpful to some one. And I mention this code can't prevent zooming triggered by browser menu.
  • programad
    programad over 2 years
    Does not work on Chrome on MacOS today.
  • SGP
    SGP about 2 years
    Yeah, it no longer works