Basj
Basj

Reputation: 46353

Prevent zoom cross-browser

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:


How to prevent zooming cross-browser ?

Upvotes: 73

Views: 134966

Answers (16)

user28424030
user28424030

Reputation: 1

Quoting relevant mozzila docs, regarding addEventListener() method:

... passive Optional

A boolean value that, if **true**, indicates that the function specified by listener will never call **preventDefault()**. **If a

passive listener calls preventDefault(), nothing will happen and a console warning may be generated.**

If this option is not specified it defaults to false – except that in browsers other than Safari, it defaults to true for wheel, mousewheel, touchstart and touchmove events. See Using passive listeners to learn more... addEventListener

That's the reason why some of the answers mentioned above didn't work at all, because using "e.preventDefault()", called from within a function, binded with "onwheel" event using standard call of addEventListener, without explicitly forcing { passive: false }, were creating in fact not active (like for most events) but passive listener in which e.preventDefault() simply does nothing, that's exactly what's happening under Chrome/Opera/FF.

Upvotes: 0

Unknowndotexe
Unknowndotexe

Reputation: 1

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>

Upvotes: 0

3i10
3i10

Reputation: 1

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

Upvotes: 0

Chroma
Chroma

Reputation: 107

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 });

Upvotes: 1

Himanshu Singh Chauhan
Himanshu Singh Chauhan

Reputation: 433

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'>

Upvotes: 6

Jian Zhong
Jian Zhong

Reputation: 501

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.

Upvotes: 3

Vijay Dhanvai
Vijay Dhanvai

Reputation: 1116

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.

Upvotes: 40

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;
});

Upvotes: -1

Jeremy Levett
Jeremy Levett

Reputation: 947

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>

Upvotes: 11

rfornal
rfornal

Reputation: 5122

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.

Upvotes: 1

Andrii Gordiichuk
Andrii Gordiichuk

Reputation: 1947

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.

Upvotes: 4

B. Colin Tim
B. Colin Tim

Reputation: 331

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>

Upvotes: 1

Shanu Shaji
Shanu Shaji

Reputation: 134

$(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();
               }

      });
  })

Upvotes: 1

thunder
thunder

Reputation: 230

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>

Upvotes: 9

David
David

Reputation: 4883

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.

Upvotes: 6

hon2a
hon2a

Reputation: 7214

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:

Upvotes: 48

Related Questions