How to detect page zoom level in all modern browsers?

后端 未结 28 1828
慢半拍i
慢半拍i 2020-11-21 05:27
  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.

相关标签:
28条回答
  • 2020-11-21 06:04

    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.

    0 讨论(0)
  • 2020-11-21 06:04
    @media (min-width: 500px){
    /* css here */
    }
    

    or

    @media (max-width: 500px){
    /* css here */
    }
    
    0 讨论(0)
  • 2020-11-21 06:06

    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>
    
    0 讨论(0)
  • 2020-11-21 06:06

    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 (%).

    0 讨论(0)
  • 2020-11-21 06:07

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

    0 讨论(0)
  • 2020-11-21 06:08
    zoom = ( window.outerWidth - 10 ) / window.innerWidth
    

    That's all you need.

    0 讨论(0)
提交回复
热议问题