12

I have a problem with Safari in a web application that contains a position:fixed element. When the page is zoomed out (smaller 100%) things break and would need to be fixed by calling a function. So I'd like to detect the user's zooming. I found this jQueryPlug-in a while ago:

http://mlntn.com/2008/12/11/javascript-jquery-zoom-event-plugin/

http://mlntn.com/demos/jquery-zoom/

It detects keyboard and mouse events that might lead to a page zoom level change. Fair enough. It works on current FF and IE but not on Safari. Any ideas what could be done to do something simmilar in current WebKit browsers?

JackWhiteIII
  • 1,388
  • 2
  • 11
  • 25
C.O.
  • 2,281
  • 6
  • 28
  • 51

4 Answers4

24

It's not a direct duplicate of this question since that deals with Mobile Safari, but the same solution will work.

When you zoom in, window.innerWidth is adjusted, but document.documentElement.clientWidth is not, therefore:

var zoom = document.documentElement.clientWidth / window.innerWidth;

Furthermore, you should be able to use the onresize event handler (or jQuery's .resize()) to check for this:

var zoom = document.documentElement.clientWidth / window.innerWidth;
$(window).resize(function() {
    var zoomNew = document.documentElement.clientWidth / window.innerWidth;
    if (zoom != zoomNew) {
        // zoom has changed
        // adjust your fixed element
        zoom = zoomNew
    }
});
Community
  • 1
  • 1
newtron
  • 5,938
  • 1
  • 23
  • 19
  • 4
    I just tested this theory on Chrome and I seem to always get a ratio pretty close to 1, whether I'm zoomed to 100%, 67%, or 175%. on a side note, jQuery's `$(window).width()` returns the same value as `document.documentElement.clientWidth`, whereas `window.innerWidth` is generally slightly larger (although not enough to reflect the zoom amount). – redbmk Apr 01 '13 at 06:55
  • 1
    window.innerWidth is not the exactly width if appear the scrollbar. You have to do window.innerWidth - 17 to get 1 when there is no zoom – ccsakuweb Apr 08 '13 at 10:48
  • In this case, don't check if they are exactly equal (===) but check if their difference is smaller than 1 (Math.abs(element.scrollTop + element.height - child.innerHeight) < 1)) That should work for most cases – Marcos Pereira Aug 05 '15 at 22:49
2

There is a nifty plugin built from yonran that can do the detection. Here is his previously answered question on StackOverflow. It works for most of the browsers. Application is as simple as this:

window.onresize = function onresize() {
  var r = DetectZoom.ratios();
  zoomLevel.innerHTML =
    "Zoom level: " + r.zoom +
    (r.zoom !== r.devicePxPerCssPx
        ? "; device to CSS pixel ratio: " + r.devicePxPerCssPx
        : "");
}

Demo

Community
  • 1
  • 1
Starx
  • 77,474
  • 47
  • 185
  • 261
1

srceen.width is fixed value but where as window.innerWidth value will change as per the zoom effect. please try the below code:

 $(window).resize(function() {
   if(screen.width == window.innerWidth){
       alert("you are on normal page with 100% zoom");
   } else if(screen.width > window.innerWidth){
       alert("you have zoomed in the page i.e more than 100%");
   } else {
       alert("you have zoomed out i.e less than 100%");
   }
});
Dinnu Buddy
  • 369
  • 1
  • 3
  • 13
1

Differentiate between window resize, browser zoom change, and system dpi change

;(() => {
  const last = {
    devicePixelRatio: devicePixelRatio,
    innerWidth: innerWidth,
    innerHeight: innerHeight,
    outerWidth: outerWidth,
    outerHeight: outerHeight,
  }
      
  const browser = navigator.appVersion.includes('WebKit')
  
  const almostZero = n => n <= 1 && n >= -1
  
  window.addEventListener('resize', () => {
    if (last.devicePixelRatio !== devicePixelRatio) {
      if (browser ? almostZero(last.innerWidth - innerWidth) && almostZero(last.innerHeight - innerHeight)
          :almostZero(last.outerWidth - outerWidth) && almostZero(last.outerHeight - outerHeight)) {
        console.log('system wide dpi change')
      } else {
        console.log('browser level zoom change')
      }
    } else {
      console.log('window resize')
    }
    last.devicePixelRatio = devicePixelRatio
    last.innerWidth = innerWidth
    last.innerHeight = innerHeight
    last.outerWidth = outerWidth
    last.outerHeight = outerHeight
  })
})()

Works in Chrome & Firefox on Windows

Monday Fatigue
  • 223
  • 1
  • 3
  • 19