javascriptbrowserzoomingdetection

How to detect page zoom level in all modern browsers?


  1. 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.

  2. 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.

  3. 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>

Solution

  • 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. [↑ broken link. Archived copy → here].

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

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

    var a = 0.1; // start of the search range
    var b = 5; // end of the search range
    var maxIter = 20; // maximum number of iterations
    var epsilon = 0.01; // tolerance
    
    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);
    
    console.log(mozDevicePixelRatio)
    console.log(ff35DevicePixelRatio)
    <style id=binarysearch></style>
    <div id=dummyElement>Dummy element to test media queries.</div>