Prevent zoom cross-browser
Asked Answered
R

15

72

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 ?

Rastus answered 24/11, 2014 at 23:36 Comment(17)
@Skoua: it's possible to override these shortcuts. I successfully did (with window.onkeydown and e.preventDefault()). My question is : how to prevent from zooming from the browser's menu (View > Zoom settings, etc.)Rastus
just listen to 'ctrl' combined with 'mouse wheel' - most users zoom in and out while holding ctrl down and scrolling the wheel.. for those who go all the way to the menu to zoom in / out - let them be :)Fanchan
If this was on flash, it would be a different story. Regardless, I've been trying to build a script that detects the browser's zoom level and applies the opposite effect with css using zoom but it's more difficult than I thought. (using tombigel.github.io/detect-zoom)Blader
I can just as easily resize my browser window, or change my resolution, which layout wise has the same effect as zooming. So what are you actually trying to prevent? Are you really trying to make your site only work with one resolution?Leralerch
@David: here is my website, you will see why I want to avoid "standard" browser zooming : bigpicture.bi/demoRastus
@Basj, good reason. There's still no way to do stop it, but it looks like there is a way to counteract it, which I just put into an answer.Leralerch
You could technically make all sizes relative so scrolling wouldn't do anything.Circumfluous
Also worth noting that some of us who have high res monitors have a default zoom value that isn't 100% - so even if you detect the zoom change event, you're not starting from a known positionMichaelamichaele
@Rastus Nice app, but I don't see the gain from preventing browser zoom. (I see that it doesn't make sense to use browser zoom when using the app, but that's not the same thing.)Schumann
@Basj: Just don't do this. Seriously. Parts of your app as things stand border on unreadable for old, tired eyes. Disabling zooming serves absolutely no point except irritating users. (Also, tbh, overriding the scroll to make things zoom in and out is awkward to the point that your site ended up being a useless white screen within 10s of me trying it and getting lost in it.)Tertia
@Denis you have "click on the BigPicture logo" or the keyboard shortcut "F2" for that : it would bring you back to "see the bigpicture" : bigpicture.bi/demo . Something else: I don't understand a part of your comment: if unreadable, just use the zooming that I provide in the app (instead of the browser internal zoom that makes no sense in this app)Rastus
@Basj, don't forget to award the bounty to whoever helped the most.Leralerch
Yes @Leralerch I will award it. Currently here : gget.it/vtn8i8rb/NFB92BF.HTML, only CTRL+ / CTRL- is disabled. Can we update it, as much as we can (of course, it won't work on every browser) with the different techniques provided here?Rastus
@Basj, I see your demo has zoom disabled, at least on the navbar. And it seems disabled even on Firefox desktop. How'd you finally manage it?Venturous
Maybe it's a matter of detecting zoom and then scaling the elements accordinglyGaribold
For what it’s worth, as of this writing, it appears that zoom: reset not even supported in Chrome anymore (I’m using Chrome 77).Levey
Check my answer follow, just add {passive: false} when addEventerListener window.addEventListener("wheel", handleWheel, {passive: false}); https://mcmap.net/q/273824/-prevent-zoom-cross-browser/…Hogfish
S
46

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:

Schumann answered 28/11, 2014 at 8:30 Comment(2)
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.Schumann
Check my answer follow, just add {passive: false} when addEventerListener window.addEventListener("wheel", handleWheel, {passive: false}); https://mcmap.net/q/273824/-prevent-zoom-cross-browser/…Hogfish
C
40

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.

Curkell answered 30/6, 2015 at 7:18 Comment(4)
Ctrl and + make it zoomGodmother
Yes it Zoom in chrome browser, Now check again i have update condition.Curkell
This no longer works as of 2020 in any of the browsers I testedVannessavanni
The fix for chrome might be attaching wheel event to some div wrapper, but not to the window/document/body itself, chromestatus.com/feature/6662647093133312.Sansbury
L
11

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>
Lumberjack answered 1/8, 2018 at 15:46 Comment(0)
M
9

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>
Mosesmosey answered 29/11, 2014 at 21:3 Comment(0)
L
6

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.

Leralerch answered 30/11, 2014 at 2:3 Comment(3)
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.Myer
Do you think @Leralerch 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 disabledRastus
@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.Leralerch
M
4

I updated code Vijay code:

$(document).ready(function(){
 var keyCodes = [61, 107, 173, 109, 187, 189];

 $(document).keydown(function(event) {   
   if (event.ctrlKey==true && (keyCodes.indexOf(event.which) != -1)) {
     alert('disabling zooming'); 
     event.preventDefault();
    }
 });

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

This solution is cross-platform (OS / Win) for desktop browsers.

Mho answered 20/10, 2015 at 13:58 Comment(4)
I pasted your code into jsfiddle.net and I can still zoom on a mac using Command +Illicit
@NestMan, I think you forgot put }); in the end.Mho
This prevents it from zooming, great job, but if you really try to scroll zoom it still zooms on chrome.Tribunate
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).Dizon
N
4

Following code can prevent all types of zoom with mouse, keyboard gestures

document.addEventListener(
    "wheel",
    function touchHandler(e) {
      if (e.ctrlKey) {
        e.preventDefault();
      }
    }, { passive: false } );

For mobile just add the following lines <meta name='viewport' content='width=device-width,initial-scale=1,user-scalable=no, maximum-scale=1.0, shrink-to-fit=no'>

Notecase answered 28/6, 2022 at 6:2 Comment(1)
good answer nice and simple. Human readability matters. Thank you. Although the description could be batter. This does not prevent keyboard + - zooming. That's fine by me, just need to disable ctrl+scroll and this answer is perfect for that.Beanery
H
3

Prevent browser zooming by keyboard is as same as above many answers.

window.addEventListener('keydown', function (e) {
    if ((e.ctrlKey || e.metaKey) && (e.which === 61 || e.which === 107 || e.which === 173 || e.which === 109 || e.which === 187 || e.which === 189)) {
        e.preventDefault();
    }
}, false);

But prevent zooming by mouse wheel is different in modern browser now. The new policy of Chrome need you use passive = false explicitly.

{passive: false}

If not, event.preventDefault() can't stop the default action browser zooming by mouse wheel event, check it.

const handleWheel = function(e) {
    if(e.ctrlKey || e.metaKey)
        e.preventDefault();
};
window.addEventListener("wheel", handleWheel, {passive: false});

But we can’t prevent clicking to zoom from the browser menu.

Hogfish answered 25/10, 2021 at 14:2 Comment(2)
Please read the question in full. It's not about reacting to mouse wheel events.Schumann
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.Hogfish
E
1

Have you tried ...

$("body").css({
     "-moz-transform":"scale(1)",
     "-webkit-transform":"scale(1)",
     "-o-transform":"scale(1)",
     "-ms-transform":"scale(1)"
});

I've used this type of code to set or re-set the scale.

Emmanuel answered 4/12, 2014 at 18:23 Comment(2)
This does not worksMiddelburg
Given that the answer is from eight (8) years ago, I'm not surprised. These are very specific targetted transforms using jQuery in a pattern I wouldn't try today. There were some odd things we had to do. Just glancing, a CSS body { transform: scale(1); } might work.Emmanuel
G
1
$(document).ready(function () {
      $(document).keydown(function (event) {
          if (event.ctrlKey == true && (event.which == '107' || event.which == '109' || event.which == '187' || event.which == '189'))
           {
               event.preventDefault();
           }
       });

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

      });
  })
Godmother answered 5/3, 2015 at 5:26 Comment(0)
W
1

It is simple:

function load(){
  document.body.addEventListener("wheel", zoomShortcut); //add the event
}

function zoomShortcut(e){
  if(e.ctrlKey){            //[ctrl] pressed?
    event.preventDefault();  //prevent zoom
    if(e.deltaY<0){        //scrolling up?
                            //do something..
      return false;
    }
    if(e.deltaY>0){        //scrolling down?
                            //do something..
      return false;
    }
  }
}
p {
  display: block;
  background-color: #eeeeee;
  height: 100px;
}
<!DOCTYPE html>
<html>
  <head>
    <title>Mousewheel control!</title>
  </head>
  <body onload="load()">
    <p>If your Mouse is in this Box, you can't zoom.</p>
  </body>
</html>
Welcher answered 5/11, 2016 at 11:7 Comment(2)
PS: You can do this with CSS for webkit browsers like this:Welcher
Control + Numpad +/- ?Arissa
R
1

Just tested this in the latest Chrome and it works fine. Give it a go.

window.addEventListener('wheel', e => {
  if (e.ctrlKey) {
    e.preventDefault();
  }
}, { passive: false });
Riley answered 16/12, 2022 at 7:4 Comment(0)
S
0

If you are ready to brute force, you can set all the dimensions in your DOM in px so that when the browser window resizes Or the webpage is zoomed all your dimensions remain the same.

Although there is a problem, if the dimensions do not change when window resizes, it destroys the responsiveness of your website. To prevent that i believe you have to make a hell lot of media queries to make the website step-wise responsive.

OR

You can try to keep the body dimensions in px and then use % for its child. So that you only need to change the body dimensions in the media queries. But this also mean in between media queries you will have overflow of body element. And I don't know how to tackle that

Sanyu answered 16/6, 2023 at 11:41 Comment(0)
J
0

window.addEventListener('wheel', e => {
  if (e.ctrlKey) {
    e.preventDefault();
  }
}, { passive: false });

document.addEventListener('keydown', function (event) {
    if ((event.ctrlKey || event.metaKey) && event.key === '-') {
        event.preventDefault();
    }
});

document.addEventListener('keydown', function (event) {
  if (event.code === 'NumpadAdd' || event.code === 'Equal') { 
      event.preventDefault();
  }
});
body {
    font-family: 'Open Sans', sans-serif; 
    line-height: 1.6;                     
    margin: 0;                            
}

h1 {
    font-size: 1.8em;                 
    font-weight: 600;                
    margin-bottom: 1em;              
}

p {
    font-size: 1.1em;                
}

body {
    background-color: #f5f5f5;        
    color: #333;                     
}

h1 {
    color: #007bff;                  
}

section {
    padding: 2em;                     
    margin-bottom: 2em;              
}

h1 {
    text-shadow: 3px 3px 3px rgba(0, 0, 0, 0.1); 
}
<!DOCTYPE html>
<html>
<head>
    <title>Hello, World!</title>
</head>
<body>
    <h1>Thank you,
    <br> https://stackoverflow.com/users/15114231/chroma 
    <br> for the first lines of code! [line 1 - 5]</h1>
    <h2> Tested on Microsoft Edge for Business Version 127.0.2651.15 (Official build) stable app, beta channel (64-bit)</h2>
</body>
</html>
Janettajanette answered 29/6, 2024 at 12:14 Comment(0)
D
-1

This disables it for chrome and safari. I haven't tested it on other browsers https://jsfiddle.net/gjqpLfht/

$(document).ready(function() {
    $(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')) {
            alert('disabling zooming');
            event.preventDefault();
            // 107 Num Key  +
            //109 Num Key  -
            //173 Min Key  hyphen/underscor Hey
            // 61 Plus key  +/=
        }
    });

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


document.addEventListener("gesturestart", function(e) {
    e.preventDefault();
    document.body.style.zoom = 0.99;
});

document.addEventListener("gesturechange", function(e) {
    e.preventDefault();

    document.body.style.zoom = 0.99;
});
document.addEventListener("gestureend", function(e) {
    e.preventDefault();
    document.body.style.zoom = 1;
});
Drama answered 17/6, 2021 at 23:50 Comment(2)
Does not work on Chrome on MacOS today.Fabron
Yeah, it no longer worksPassive

© 2022 - 2025 — McMap. All rights reserved.