ChatGPT解决这个技术问题 Extra ChatGPT

How to detect page zoom level in all modern browsers?

How can I detect the page zoom level in all modern browsers? While this thread tells how to do it in IE7 and IE8, I can't find a good cross-browser solution. Firefox stores the page zoom level for future access. On the first page load, would I be able to get the zoom level? Somewhere I read it works when a zoom change occurs after the page is loaded. Is there a way to trap the 'zoom' event?

I need this because some of my calculations are pixel-based and they may fluctuate when zoomed.

Modified sample given by @tfl

This page alerts different height values when zoomed. [jsFiddle]

<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js" type="text/javascript"/></script>
    </head>
    <body>
        <div id="xy" style="border:1px solid #f00; width:100px;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque sollicitudin tortor in lacus tincidunt volutpat. Integer dignissim imperdiet mollis. Suspendisse quis tortor velit, placerat tempor neque. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent bibendum auctor lorem vitae tempor. Nullam condimentum aliquam elementum. Nullam egestas gravida elementum. Maecenas mattis molestie nisl sit amet vehicula. Donec semper tristique blandit. Vestibulum adipiscing placerat mollis.</div>
        <button onclick="alert($('#xy').height());">Show</button>
    </body>
</html>
Basically I want to know the dimension of a DIV at 100% zoom.
Basically there is no way to detect zoom in 2019: I have tested all the below solutions on Chrome 78 on Mac Catalina and none of them worked.

C
Claude

Now it's an even bigger mess than it was when this question was first asked. From reading all the responses and blog posts I could find, here's a summary. I also set up this page to test all these methods of measuring the zoom level.

Edit (2011-12-12): I've added a project that can be cloned: https://github.com/tombigel/detect-zoom

IE8: screen.deviceXDPI / screen.logicalXDPI (or, for the zoom level relative to default zoom, screen.systemXDPI / screen.logicalXDPI)

IE7: var body = document.body,r = body.getBoundingClientRect(); return (r.left-r.right)/body.offsetWidth; (thanks to this example or this answer)

FF3.5 ONLY: screen.width / media query screen width (see below) (takes advantage of the fact that screen.width uses device pixels but MQ width uses CSS pixels--thanks to Quirksmode widths)

FF3.6: no known method

FF4+: media queries binary search (see below)

WebKit: https://www.chromestatus.com/feature/5737866978131968 (thanks to Teo in the comments)

WebKit: measure the preferred size of a div with -webkit-text-size-adjust:none.

WebKit: (broken since r72591) document.width / jQuery(document).width() (thanks to Dirk van Oosterbosch above). To get ratio in terms of device pixels (instead of relative to default zoom), multiply by window.devicePixelRatio.

Old WebKit? (unverified): parseInt(getComputedStyle(document.documentElement,null).width) / document.documentElement.clientWidth (from this answer)

Opera: document.documentElement.offsetWidth / width of a position:fixed; width:100% div. from here (Quirksmode's widths table says it's a bug; innerWidth should be CSS px). We use the position:fixed element to get the width of the viewport including the space where the scrollbars are; document.documentElement.clientWidth excludes this width. This is broken since sometime in 2011; I know no way to get the zoom level in Opera anymore.

Other: Flash solution from Sebastian

Unreliable: listen to mouse events and measure change in screenX / change in clientX

Here's a binary search for Firefox 4, since I don't know of any variable where it is exposed:

<style id=binarysearch></style>
<div id=dummyElement>Dummy element to test media queries.</div>
<script>
var mediaQueryMatches = function(property, r) {
  var style = document.getElementById('binarysearch');
  var dummyElement = document.getElementById('dummyElement');
  style.sheet.insertRule('@media (' + property + ':' + r +
                         ') {#dummyElement ' +
                         '{text-decoration: underline} }', 0);
  var matched = getComputedStyle(dummyElement, null).textDecoration
      == 'underline';
  style.sheet.deleteRule(0);
  return matched;
};
var mediaQueryBinarySearch = function(
    property, unit, a, b, maxIter, epsilon) {
  var mid = (a + b)/2;
  if (maxIter == 0 || b - a < epsilon) return mid;
  if (mediaQueryMatches(property, mid + unit)) {
    return mediaQueryBinarySearch(
        property, unit, mid, b, maxIter-1, epsilon);
  } else {
    return mediaQueryBinarySearch(
        property, unit, a, mid, maxIter-1, epsilon);
  }
};
var mozDevicePixelRatio = mediaQueryBinarySearch(
    'min--moz-device-pixel-ratio', '', a, b, maxIter, epsilon);
var ff35DevicePixelRatio = screen.width / mediaQueryBinarySearch(
    'min-device-width', 'px', 0, 6000, 25, .0001);
</script>

Very nice work, although this does't work for me in IE 8.0.7601.17514 (latest). Any chance to wrap all this up in a single function getZoom() that works across all browsers? Perhaps also release as a jQuery plugin? Nice work again.
@yonran great plugin!, But it does not work in IE9 it should be zoom: screen.deviceXDPI / screen.logicalXDPI, instead of zoom: screen.systemXDPI / screen.logicalXDPI,
@RobW, when I first wrote this for Firefox 4, Firefox didn’t have matchMedia. Paul Irish also wrote a similar matchMedia polyfill that is part of Modernizr.
Good news, everyone! They finaly did it! Vieport API! chromestatus.com/feature/5737866978131968 I test it, great stuff!
The Viewport API only works for pinch-zoom; if you zoom on desktop it says scale is 1. @Jason T Featheringham there are reasons other than "discrimination" to want to know the zoom level. Zoom is set across all pages for a domain, but you might want to handle it differently in a game page or an extension popup than you do in a help page.
C
Clokman

You can try

var browserZoomLevel = Math.round(window.devicePixelRatio * 100);

This will give you browser zoom percentage level on non-retina displays. For high DPI/retina displays, it would yield different values (e.g., 200 for Chrome and Safari, 140 for Firefox).

To catch zoom event you can use

$(window).resize(function() { 
// your code 
});

Works perfect, also on mobile devices. It is also quite interesting to see what mobile devices have what devicePixelRatio. This also greatly helped me switching a fixed element to absolutely positioned element when the zoom event occurs, or when the inital value of devicePixelRatio changes. Perfect! Thank you!!
Doesn't work as expected: It returns 200 in Chrome on MacBook with retina when browser not zoomed.
Browsers with support for high DPI screens will not give the expected outcome when using such display, neither will Safari regardless of display.
Math.round(window.devicePixelRatio * 100) works on Chrome, IE, Edge, and Firefox. Safari on iMac always returns 200.
This doesn't work on Chrome on Retina displays, as the default value is not 1, but 2. Different screens with different pixel densities should deliver different values.
R
RamenChef

For me, for Chrome/Webkit, document.width / jQuery(document).width() did not work. When I made my window small and zoomed into my site such that horizontal scrollbars appeared, document.width / jQuery(document).width() did not equal 1 at the default zoom. This is because document.width includes part of the document outside the viewport.

Using window.innerWidth and window.outerWidth worked. For some reason in Chrome, outerWidth is measured in screen pixels and innerWidth is measured in css pixels.

var screenCssPixelRatio = (window.outerWidth - 8) / window.innerWidth;
if (screenCssPixelRatio >= .46 && screenCssPixelRatio <= .54) {
  zoomLevel = "-4";
} else if (screenCssPixelRatio <= .64) {
  zoomLevel = "-3";
} else if (screenCssPixelRatio <= .76) {
  zoomLevel = "-2";
} else if (screenCssPixelRatio <= .92) {
  zoomLevel = "-1";
} else if (screenCssPixelRatio <= 1.10) {
  zoomLevel = "0";
} else if (screenCssPixelRatio <= 1.32) {
  zoomLevel = "1";
} else if (screenCssPixelRatio <= 1.58) {
  zoomLevel = "2";
} else if (screenCssPixelRatio <= 1.90) {
  zoomLevel = "3";
} else if (screenCssPixelRatio <= 2.28) {
  zoomLevel = "4";
} else if (screenCssPixelRatio <= 2.70) {
  zoomLevel = "5";
} else {
  zoomLevel = "unknown";
}

Very nice. And if you only need to know whether it's zoomed or not in Chrome: isZoomed = (screenCssPixelRatio < .98 || screenCssPixelRatio > 1.02)
Well, window.outerWidth is changed with the zoom too. Also, not on every OS the window border width is 8 pixels (even on same OS the design can vary). However I would suggest to substract 16, not 8, since you have the window borders twice. Also, some browser have a border on their actual rendering window (like FF) and some not (Safari) - but even this depends on which OS you use the browser (e. g. Safari has a border on Windows). Backing up the initial innerWidth (e. g. on page load) and use it to compare works better but only if initional zoom was 100%...
Outputs 0 no matter what for me (2017, feb).
switch statement may be better than many if else statements.
This is working in Chrome and Edge however both browsers include the debug (F12) window in the outerWidth so if this is open your results will vary wildly.
J
Jay

My coworker and I used the script from https://github.com/tombigel/detect-zoom. In addition, we also dynamically created a svg element and check its currentScale property. It works great on Chrome and likely most browsers too. On FF the "zoom text only" feature has to be turned off though. SVG is supported on most browsers. At the time of this writing, tested on IE10, FF19 and Chrome28.

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
svg.setAttribute('version', '1.1');
document.body.appendChild(svg);
var z = svg.currentScale;
... more code ...
document.body.removeChild(svg);

This method now always report svg.currentScale = 1 in Firefox 29. Probably because they resize the entire screen figures based on zoom which is a bug. IE11 seem to have the same problem on Desktop with the screen height adjusted to the viewport devicePixelRatio which is quite screwed up.
The only one that actually works. Of course if you already have a svg in there that is better.
b
brianh

I found this article enormously helpful. Huge thanks to yonran. I wanted to pass on some additional learning I found while implementing some of the techniques he provided. In FF6 and Chrome 9, support for media queries from JS was added, which can greatly simplify the media query approach necessary for determining zoom in FF. See the docs at MDN here. For my purposes, I only needed to detect whether the browser was zoomed in or out, I had no need for the actual zoom factor. I was able to get my answer with one line of JavaScript:

var isZoomed = window.matchMedia('(max--moz-device-pixel-ratio:0.99), (min--moz-device-pixel-ratio:1.01)').matches;

Combining this with the IE8+ and Webkit solutions, which were also single lines, I was able to detect zoom on the vast majority of browsers hitting our app with only a few lines of code.


Could you please provide a code how to detect actual zoom using media query?
Try using just "(width: px) and (height: px)" where and are window.innerWidth and window.innerHeight, respectively. It works even for very tiny amounts of zoom. Works in Safari too.
@max Can you provide a JSFIddle or sample code of how this looks put together please?
Always reports true on retina devices such as macbook pro.
codepen.io/anon/pen/LgrGjJ shows a binary search with media queries, but this is the same as querying devicePixelRatio: it takes into account display scaling.
A
Alex von Thorn
zoom = ( window.outerWidth - 10 ) / window.innerWidth

That's all you need.


Why subtract 10 from outerWidth?
Probably for the scrollbar. Each scrollbar is different too, like in iOS its much smaller. Plus this solution seems to be chrome only
It does not work if the user has a side bar such as bookmarks in FF
Please consider adding an explanation, especially when using a magic number.
T
Terite

I have a solution for this as of Jan 2016. Tested working in Chrome, Firefox and MS Edge browsers.

The principle is as follows. Collect 2 MouseEvent points that are far apart. Each mouse event comes with screen and document coordinates. Measure the distance between the 2 points in both coordinate systems. Although there are variable fixed offsets between the coordinate systems due to the browser furniture, the distance between the points should be identical if the page is not zoomed. The reason for specifying "far apart" (I put this as 12 pixels) is so that small zoom changes (e.g. 90% or 110%) are detectable.

Reference: https://developer.mozilla.org/en/docs/Web/Events/mousemove

Steps:

Add a mouse move listener window.addEventListener("mousemove", function(event) { // handle event }); Capture 4 measurements from mouse events: event.clientX, event.clientY, event.screenX, event.screenY Measure the distance d_c between the 2 points in the client system Measure the distance d_s between the 2 points in the screen system If d_c != d_s then zoom is applied. The difference between the two tells you the amount of zoom.

N.B. Only do the distance calculations rarely, e.g. when you can sample a new mouse event that's far from the previous one.

Limitations: Assumes user will move the mouse at least a little, and zoom is unknowable until this time.


I created a fiddle: jsfiddle.net/Terite/9b6ko854 with "far apart" meant as 100 pixels. Unfortunately it works unstable on Firefox (52) on MacBook with retina display. Also should be noted that Window 7 interface zoom 125% is detected in Chrome, Firefox and IE11 (in zoom 125% which is default then) as a browser zoom.
Your fiddle works for me, tested in Linux with Firefox and Chrome :)
Retina displays add another level of difficulty because they report the pixel sizes incorrectly, among other things.
c
collimarco

You can use the Visual Viewport API:

window.visualViewport.scale;

It is standard and works both on desktop and mobile: browser support.


Looks handy, but it's still disabled by default in Firefox desktop, and doesn't work in Internet Explorer as of 5/31/20.
This property returns the value of a pinch zoom but not the browser's zoom level (CMD + '+').
M
Maxim Kolesnikov

What i came up with is :

1) Make a position:fixed <div> with width:100% (id=zoomdiv)

2) when the page loads :

zoomlevel=$("#zoomdiv").width()*1.0 / screen.availWidth

And it worked for me for ctrl+ and ctrl- zooms.

or i can add the line to a $(window).onresize() event to get the active zoom level

Code:

<script>
    var zoom=$("#zoomdiv").width()*1.0 / screen.availWidth;

    $(window).resize(function(){
        zoom=$("#zoomdiv").width()*1.0 / screen.availWidth;
        alert(zoom);    
    });
</script>
<body>
    <div id=zoomdiv style="width:100%;position:fixed;"></div>
</body>

P.S. : this is my first post, pardon any mistakes


Unfortunately, this will only work if the user has the browser maximized (screen.availWidth reports the width of the screen in screen pixels, not the browser window).
k
kirilloid

Basically, we have:

window.devicePixelRatio which takes into account both browser-level zoom* as well as system zoom/pixel density. * — on Mac/Safari zoom level is not taken into account

media queries

vw/vh CSS units

resize event, which is triggered upon zoom level change, cause effective size of the window changes

that should be enough for normal UX. If you need to detect zoom level that might be a sign of bad UI design.

Pitch-zoom is harder to track and is not considered currently.


window.devicePixelRatio is a good answer that works in the latest version of the major browsers - Chrome, Safari, FF, Edge, IE
@kirilloid did you find anything that could be used to reliably find the "zoom level" in Safari?
J
Julien Kronegg

In Internet Explorer 7, 8 & 9, this works:

function getZoom() {
    var screen;

    screen = document.frames.screen;
    return ((screen.deviceXDPI / screen.systemXDPI) * 100 + 0.9).toFixed();
}

The "+0.9" is added to prevent rounding errors (otherwise, you would get 104% and 109% when the browser zoom is set to 105% and 110% respectively).

In IE6 zoom doesn't exists, so it is unnecessary to check the zoom.


Interesting. For me, it always shows 80% of the zoom ... I believe this is because I have large fonts setup at the Windows 7 level (search for "font size" in control panel). It's better than the IE8 solution in @yonran's answer that didn't work at all for me. jsbin.com/obowof
I am getting 101% when the zoom is set to 100%.
me too. use 0.4999 instead of 0.9
ieZoomLevel = ((screen.deviceXDPI / screen.systemXDPI) * 100 + 0.4999).toFixed();
T
Timo Tijhof

This has worked great for me in webkit-based browsers (Chrome, Safari):

function isZoomed() {
    var width, mediaQuery;

    width = document.body.clientWidth;
    mediaQuery = '(max-width: ' + width + 'px) and (min-width: ' + width + 'px)';

    return !window.matchMedia(mediaQuery).matches;
}

Doesn't seem to work in Firefox though.

This also works in WebKit:

var zoomLevel = document.width / document.body.clientWidth;

document.width returns undefined
Always returns true no matter the zoom (2017, feb, retina display).
N
Nicolas Giszpenc

On Chrome

var ratio = (screen.availWidth / document.documentElement.clientWidth);
var zoomLevel = Number(ratio.toFixed(1).replace(".", "") + "0");

Works only when browser window has the full width of the screen.
A
Abd Abughazaleh

try this

alert(Math.round(window.devicePixelRatio * 100));

This will work only for non retina displays.
J
JIm

On mobile devices (with Chrome for Android or Opera Mobile) you can detect zoom by window.visualViewport.scale. https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API

Detect on Safari: document.documentElement.clientWidth / window.innerWidth (return 1 if no zooming on device).


The visualViewport.scale shows pinch zoom, but not the page actual zoom.
N
Neil

Your calculations are still based on a number of CSS pixels. They're just a different size on the screen now. That's the point of full page zoom.

What would you want to happen on a browser on a 192dpi device which therefore normally displayed four device pixels for each pixel in an image? At 50% zoom this device now displays one image pixel in one device pixel.


@Neil: how can I get 'CSS pixels' dimensions?
CSS defaults to points, but you can of course specify pixels by using the px dimension modifier. As for element properties retrieved in JavaScript, these should already be in CSS pixels. So if you specify the width of a
to be 100px, then that's what you'll get back from JavaScript, whatever the zoom level may be.
D
Dirk van Oosterbosch

Didn't test this for IE, but if you make an element elem with

min-width: 100%

then

window.document.width / elem.clientWidth

will give you your browser zoom level (including the document.body.style.zoom factor).


Tested this but zooming in does not seem to increase elem.clientWidth
C
Community

This is for Chrome, in the wake of user800583 answer ...

I spent a few hours on this problem and have not found a better approach, but :

There are 16 'zoomLevel' and not 10

When Chrome is fullscreen/maximized the ratio is window.outerWidth/window.innerWidth, and when it is not, the ratio seems to be (window.outerWidth-16)/window.innerWidth, however the 1st case can be approached by the 2nd one.

So I came to the following ...

But this approach has limitations : for example if you play the accordion with the application window (rapidly enlarge and reduce the width of the window) then you will get gaps between zoom levels although the zoom has not changed (may be outerWidth and innerWidth are not exactly updated in the same time).

var snap = function (r, snaps)
{
    var i;
    for (i=0; i < 16; i++) { if ( r < snaps[i] ) return i; }
};
var w, l, r;
w = window.outerWidth, l = window.innerWidth;
return snap((w - 16) / l,
            [ 0.29, 0.42, 0.58, 0.71, 0.83, 0.95, 1.05, 1.18, 1.38, 1.63, 1.88, 2.25, 2.75, 3.5, 4.5, 100 ],
);

And if you want the factor :

var snap = function (r, snaps, ratios)
{
    var i;
    for (i=0; i < 16; i++) { if ( r < snaps[i] ) return eval(ratios[i]); }
};
var w, l, r;
w = window.outerWidth, l = window.innerWidth;
return snap((w - 16) / l,
            [ 0.29, 0.42, 0.58, 0.71, 0.83, 0.95, 1.05, 1.18, 1.38, 1.63, 1.88, 2.25, 2.75, 3.5, 4.5, 100 ],
            [ 0.25, '1/3', 0.5, '2/3', 0.75, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3, 4, 5 ]
);

I had problems with "window.outerWidth/window.innerWidth" giving me the wrong value too and that might of been because I was in an iframe. So what I did is I used the parent window and it gave the correct answer: window.parent.window.outerWidth/window.parent.window.innerWidth
p
pmrotule

I have this solution for mobile only (tested with Android):

jQuery(function($){

zoom_level = function(){

    $("body").prepend('<div class="overlay" ' +
                'style="position:fixed; top:0%; left:0%; ' +
                'width:100%; height:100%; z-index:1;"></div>');

    var ratio = $("body .overlay:eq(0)").outerWidth() / $(window).width();
    $("body .overlay:eq(0)").remove();

    return ratio;
}

alert(zoom_level());

});

If you want the zoom level right after the pinch move, you will probably have to set a little timeout because of the rendering delay (but I'm not sure because I didn't test it).


C
Cameron Weaver

This answer is based on comments about devicePixelRatio coming back incorrectly on user1080381's answer.

I found that this command was coming back incorrectly in some instances too when working with a desktop, Surface Pro 3, and Surface Pro 4.

What I found is that it worked on my desktop, but the SP3 and SP4 were giving different numbers from each other and the desktop.

I noticed though that the SP3 was coming back as 1 and a half times the zoom level I was expecting. When I took a look at the display settings, the SP3 was actually set to 150% instead of the 100% I had on my desktop.

So, the solution to the comments should be to divide the returned zoom level by the scale of the machine you are currently on.

I was able to get the scale in the Windows settings by doing the following:

ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DesktopMonitor");
double deviceScale = Convert.ToDouble(searcher.Get().OfType<ManagementObject>().FirstOrDefault()["PixelsPerXLogicalInch"]);
int standardPixelPerInch = 96;
return deviceScale / standardPixelPerInch;

So in the case of my SP3, this is how this code looks at 100% zoom:

devicePixelRatio = 1.5
deviceScale = 144
deviceScale / standardPixelPerInch = 1.5
devicePixelRatio / (deviceScale / standardPixelPerInch) = 1

Multiplying by the 100 in user1080381's original answer then would give you a zoom of 100 (%).


Y
Yogi

Have it currently working however still need to separate by browser. Tested successfully on Chrome(75) and Safari(11.1) (haven't found way for FF as of yet). It also gets the zoom value correct on retina display and calculations are triggered on resize event.

    private pixelRatio() {
      const styleString = "(min-resolution: 2dppx), (-webkit-min-device-pixel-ratio: 1.5),(-moz-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)";
      const chromeRatio = (Math.round((this.window.outerWidth / this.window.innerWidth)*100) / 100);
      const otherRatio = (Math.round(window.devicePixelRatio * 100) / 100);
      const resizeValue = (this.isChrome()) ? chromeRatio : otherRatio;

      return resizeValue || (this.window.matchMedia && this.window.matchMedia(styleString).matches ? 2 : 1) || 1;
    }


  private isChrome():boolean {
    return (!!this.window.chrome && !(!!this.window.opera || this.window.navigator.userAgent.indexOf(' Opera') >= 0))
  }

  private chrome() {
    const zoomChrome = Math.round(((this.window.outerWidth) / this.window.innerWidth)*100) / 100;
    return {
      zoom: zoomChrome,
      devicePxPerCssPx: zoomChrome1 * this.pixelRatio()
    };
  }

i
iceman

This detects scale.

html code:

<body id="blog">

js:

function scale(){
return Math.round(100/(d.getElementById('blog').offsetWidth/d.getElementById('blog').getBoundingClientRect().width))/100;
}

Zoom factor and scale are not to be confused with each other. Users control "zoom"; "scale" is a CSS transformation. 11 years and 10 months ago, however, understack noted:

Basically I want to know the dimension of a DIV at 100% zoom.

This does that. I use it in conjunction with @media queries to detect in JavaScript device scaling, i.e. 360x720 might apply 0.5 scaling; 720x360, 0.75.

var d=document;

S
Shannon Hochkins

I used a different approach, i created a dom element with a fixed height and width of 100px, position fixed and opacity of 0, basically a hidden element.

I then used dom-to-image to capture this element as an image which might sound like overkill but i wanted a bullet proof solution and we were already using this package anyways, then validated the output image width, if it came back with 110, the zoom is at 110%, it's very accurate.

const ORIGINAL_ZOOM_SIZE = 100;
async function isValidateZoomLevel() {
    const base64Render = await domToImage({
      ref: hiddenElementReference,
    });
    const pixleRatio = Math.round(window.devicePixelRatio);
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(ORIGINAL_ZOOM_SIZE === img.width / pixleRatio && ORIGINAL_ZOOM_SIZE === (img.height / pixleRatio));
      img.onerror = reject;
      img.src = base64Render; 
    });
  }

R
Rob W

This may or may not help anyone, but I had a page I could not get to center correctly no matter what Css tricks I tried so I wrote a JQuery file call Center Page:

The problem occurred with zoom level of the browser, the page would shift based upon if you were 100%, 125%, 150%, etc.

The code below is in a JQuery file called centerpage.js.

From my page I had to link to JQuery and this file to get it work, even though my master page already had a link to JQuery.

<title>Home Page.</title>
<script src="Scripts/jquery-1.7.1.min.js"></script>
<script src="Scripts/centerpage.js"></script>

centerpage.js:

// centering page element
function centerPage() {
    // get body element
    var body = document.body;

    // if the body element exists
    if (body != null) {
        // get the clientWidth
        var clientWidth = body.clientWidth;

        // request data for centering
        var windowWidth = document.documentElement.clientWidth;
        var left = (windowWidth - bodyWidth) / 2;

        // this is a hack, but it works for me a better method is to determine the 
        // scale but for now it works for my needs
        if (left > 84) {
            // the zoom level is most likely around 150 or higher
            $('#MainBody').removeClass('body').addClass('body150');
        } else if (left < 100) {
            // the zoom level is most likely around 110 - 140
            $('#MainBody').removeClass('body').addClass('body125');
        }
    }
}


// CONTROLLING EVENTS IN jQuery
$(document).ready(function() {
    // center the page
    centerPage();
});

Also if you want to center a panel:

// centering panel
function centerPanel($panelControl) {
    // if the panel control exists
    if ($panelControl && $panelControl.length) {
        // request data for centering
        var windowWidth = document.documentElement.clientWidth;
        var windowHeight = document.documentElement.clientHeight;
        var panelHeight = $panelControl.height();
        var panelWidth = $panelControl.width();

        // centering
        $panelControl.css({
            'position': 'absolute',
            'top': (windowHeight - panelHeight) / 2,
            'left': (windowWidth - panelWidth) / 2
        });

        // only need force for IE6
        $('#backgroundPanel').css('height', windowHeight);
    }
}

B
Bhumi Singhal

This is question was posted like ages back, but today when i was looking for the same answer "How to detect zoom in and out event", i couldn't find one answer that would fit all the browsers.

As on now : For Firefox/Chrome/IE8 and IE9 , the zoom in and out fires a window.resize event. This can be captured using:

$(window).resize(function() {
//YOUR CODE.
});

l
lexasss

A workaround for FireFox 16+ to find DPPX (zoom level) purely with JavaScript:

var dppx = (function (precision) {
  var searchDPPX = function(level, min, divisor) {
    var wmq = window.matchMedia;
    while (level >= min && !wmq("(min-resolution: " + (level/divisor) + "dppx)").matches) {
      level--;
    }
    return level;
  };

  var maxDPPX = 5.0; // Firefox 22 has 3.0 as maximum, but testing a bit greater values does not cost much
  var minDPPX = 0.1; // Firefox 22 has 0.3 as minimum, but testing a bit smaller values does not cost anything
  var divisor = 1;
  var result;
  for (var i = 0; i < precision; i++) {
    result = 10 * searchDPPX (maxDPPX, minDPPX, divisor);
    maxDPPX = result + 9;
    minDPPX = result;
    divisor *= 10;
  }

  return result / divisor;
}) (5);

It doesn't work as expected in Firefox (52) on MacBook with retina display – returns 2 when not in zoom. I created a fiddle: jsfiddle.net/Terite/wadkh3ea
B
Bill_VA

The problem lies in the types of monitor used, a 4k monitor vs standard monitor. Chrome is by far the smartest at being able to tell us what the zoom level is just by using window.devicePixelRatio, apparently it can tell what the pixel density is and reports back the same number to matter what.

Other browsers, not so much. IE and Edge are probably the worst, as they handle zoom levels much differently. To get the same size text on a 4k monitor, you have to select 200%, instead of 100% on a standard monitor.

As of May 2018, here's what I have to detect zoom levels for a few of the most popular browsers, Chrome, Firefox, and IE11. I have it tell me what the zoom percentage is. For IE, it reports 100% even for 4k monitors that are actually at 200%, but the text size is really the same.

Here's a fiddle: https://jsfiddle.net/ae1hdogr/

If anyone would care to take a stab at other browsers and update the fiddle, then please do so. My main goal was to get these 3 browsers covered to detect if people were using a zoom factor greater than 100% to use my web application and display a notice suggesting a lessor zoom factor.


Safari on Mac Book Pro (retina screen) returns 0, Chrome on non retina screen returns correctly it seems 100, 90 etc
Returns 200 on Chrome & Firefox retina screen
佚名

here it does not change!:

<html>
 <head>
  <title></title>
 </head>
<body>
 <div id="xy" style="width:400px;">
  foobar
 </div>
 <div>
  <button onclick="alert(document.getElementById('xy').style.width);">Show</button>
 </div>
</body>
</html>

create a simple html file, click on the button. regardless of what zoom level: it will show you the width of 400px (at least with firefox and ie8)


@tfl: it's because you've fixed the width in inline-style. I've modified your sample to show my case (posted inside original question).
a
ali
function supportFullCss3()
{
    var div = document.createElement("div");
    div.style.display = 'flex';
    var s1 = div.style.display == 'flex';
    var s2 = 'perspective' in div.style;

    return (s1 && s2);
};

function getZoomLevel()
{
    var screenPixelRatio = 0, zoomLevel = 0;

    if(window.devicePixelRatio && supportFullCss3())
        screenPixelRatio = window.devicePixelRatio;
    else if(window.screenX == '0')
        screenPixelRatio = (window.outerWidth - 8) / window.innerWidth;
    else
    {
        var scr = window.frames.screen;
        screenPixelRatio = scr.deviceXDPI / scr.systemXDPI;
    }

    //---------------------------------------
    if (screenPixelRatio <= .11){ //screenPixelRatio >= .01 &&
      zoomLevel = "-7";
    } else if (screenPixelRatio <= .25) {
      zoomLevel = "-6";
    }else if (screenPixelRatio <= .33) {
      zoomLevel = "-5.5";
    } else if (screenPixelRatio <= .40) {
      zoomLevel = "-5";
    } else if (screenPixelRatio <= .50) {
      zoomLevel = "-4";
    } else if (screenPixelRatio <= .67) {
      zoomLevel = "-3";
    } else if (screenPixelRatio <= .75) {
      zoomLevel = "-2";
    } else if (screenPixelRatio <= .85) {
      zoomLevel = "-1.5";
    } else if (screenPixelRatio <= .98) {
      zoomLevel = "-1";
    } else if (screenPixelRatio <= 1.03) {
      zoomLevel = "0";
    } else if (screenPixelRatio <= 1.12) {
      zoomLevel = "1";
    } else if (screenPixelRatio <= 1.2) {
      zoomLevel = "1.5";
    } else if (screenPixelRatio <= 1.3) {
      zoomLevel = "2";
    } else if (screenPixelRatio <= 1.4) {
      zoomLevel = "2.5";
    } else if (screenPixelRatio <= 1.5) {
      zoomLevel = "3";
    } else if (screenPixelRatio <= 1.6) {
      zoomLevel = "3.3";
    } else if (screenPixelRatio <= 1.7) {
      zoomLevel = "3.7";
    } else if (screenPixelRatio <= 1.8) {
      zoomLevel = "4";
    } else if (screenPixelRatio <= 1.9) {
      zoomLevel = "4.5";
    } else if (screenPixelRatio <= 2) {
      zoomLevel = "5";
    } else if (screenPixelRatio <= 2.1) {
      zoomLevel = "5.2";
    } else if (screenPixelRatio <= 2.2) {
      zoomLevel = "5.4";
    } else if (screenPixelRatio <= 2.3) {
      zoomLevel = "5.6";
    } else if (screenPixelRatio <= 2.4) {
      zoomLevel = "5.8";
    } else if (screenPixelRatio <= 2.5) {
      zoomLevel = "6";
    } else if (screenPixelRatio <= 2.6) {
      zoomLevel = "6.2";
    } else if (screenPixelRatio <= 2.7) {
      zoomLevel = "6.4";
    } else if (screenPixelRatio <= 2.8) {
      zoomLevel = "6.6";
    } else if (screenPixelRatio <= 2.9) {
      zoomLevel = "6.8";
    } else if (screenPixelRatio <= 3) {
      zoomLevel = "7";
    } else if (screenPixelRatio <= 3.1) {
      zoomLevel = "7.1";
    } else if (screenPixelRatio <= 3.2) {
      zoomLevel = "7.2";
    } else if (screenPixelRatio <= 3.3) {
      zoomLevel = "7.3";
    } else if (screenPixelRatio <= 3.4) {
      zoomLevel = "7.4";
    } else if (screenPixelRatio <= 3.5) {
      zoomLevel = "7.5";
    } else if (screenPixelRatio <= 3.6) {
      zoomLevel = "7.6";
    } else if (screenPixelRatio <= 3.7) {
      zoomLevel = "7.7";
    } else if (screenPixelRatio <= 3.8) {
      zoomLevel = "7.8";
    } else if (screenPixelRatio <= 3.9) {
      zoomLevel = "7.9";
    } else if (screenPixelRatio <= 4) {
      zoomLevel = "8";
    } else if (screenPixelRatio <= 4.1) {
      zoomLevel = "8.1";
    } else if (screenPixelRatio <= 4.2) {
      zoomLevel = "8.2";
    } else if (screenPixelRatio <= 4.3) {
      zoomLevel = "8.3";
    } else if (screenPixelRatio <= 4.4) {
      zoomLevel = "8.4";
    } else if (screenPixelRatio <= 4.5) {
      zoomLevel = "8.5";
    } else if (screenPixelRatio <= 4.6) {
      zoomLevel = "8.6";
    } else if (screenPixelRatio <= 4.7) {
      zoomLevel = "8.7";
    } else if (screenPixelRatio <= 4.8) {
      zoomLevel = "8.8";
    } else if (screenPixelRatio <= 4.9) {
      zoomLevel = "8.9";
    } else if (screenPixelRatio <= 5) {
      zoomLevel = "9";
    }else {
      zoomLevel = "unknown";
    }

    return zoomLevel;
};

Kindly also explain how your code works. That will be helpful if some novice finds your answer.
I created a fiddle: jsfiddle.net/Terite/5n1bk9do As @AlexeySh. mentioned, it doesn't work as expected on retina display in Chrome (56), Firefox (52). It also shows 0 in zoom on Safari (10).
That's a lot of else ifs

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now