IE7 zoom level problem, where is the mouse pointer?

thumbnail

There are several cases when you need the position of the mouse pointer on a webpage (e.g. if you want to display custom tooltips or elements that follow the mouse).

The question is, how can you set the position of an element to align to the coordinates of the mouse pointer?

The answer seems simple, the cross-browser clientX and clientY properties of the event object retrieve the position of the mouse pointer relative to the top-left corner of the browser window's client area.

Additionally, the position of a fixed positioned element's top-left corner can be specified with the top and left style properties relative to the top-left corner of the browser window's client area. All right, let's look at a simple example first:

<head>
    <style>
        #flying {
            position: fixed; 
        }
    </style>

    <script>
        function UpdateFlyingObj (event) {
            var mouseX = Math.round (event.clientX);
            var mouseY = Math.round (event.clientY);

            var flyingObj = document.getElementById ("flying");
            flyingObj.style.left = mouseX + "px";
            flyingObj.style.top = mouseY + "px";

        }
    </script>
</head>
<body onmousemove="UpdateFlyingObj (event);">
    <div style="height:1000px;">
        The flying object also works for document scrolling.
    </div>

    <img id="flying" src="flying.gif" />
</body>
Unfortunately the previous example does not work in Internet Explorer 7 at non-default zoom levels. The problem is that the clientX and clientY properties retrieve the position of the mouse in physical pixel size, while in Firefox, Opera, Safari and in Internet Explorer from version 8 they return the position in logical pixel size.

What does it mean?

If the browser is not at the normal zoom level (the user has the ability to zoom in or out a web page: CTRL and +, CTRL and -),
  • the position of the mouse pointer is calculated in the default pixel size in Internet Explorer before version 8 even if the current pixel size in the document is different,
  • from Internet Explorer 8 and in Firefox, Opera and Safari, the position is calculated in the current pixel size.

For example, if the zoom level is 200%, the logical pixel size is two times greater than the physical pixel size, so the clientX and clientY properties retrieve two times greater values in Internet Explorer before version 8 than in other browsers for the same mouse position. In contrast to the clientX and clientY properties, the top and left style properties specify the position in logical pixel size in all browsers. So if you want to set the position of an element to align to the coordinates of the mouse pointer, you need to known the current zoom level in IE7.

How can you get the current zoom level in IE7?

There are several JavaScript properties and methods that use physical pixel size instead of logical pixel size in IE7 (such as the clientX and clientY properties of the event object, the clientWidth, clientHeight, offsetWidth and offsetHeight properties of the html, the getBoundingClientRect and getClientRects methods).

The clientWidth, clientHeight, offsetWidth and offsetHeight properties retrieve the size in physical pixel size only for the html element, for other elements, they contain the size in logical pixel size.

So you can get the width of the body element with the offsetWidth property in logical pixel size and with the getBoundingClientRect method in physical pixel size. Both values contain the padding, scrollbar, and the border, but exclude the margin.

The current zoom level can be determined with the help of those two values. This method only works in Internet Explorer before version 8, the two values are the same in other browsers.

Note that if you need the current zoom level in IE from version 8, use the deviceXDPI, logicalXDPI, deviceYDPI and logicalYDPI properties.

This example is the same as the previous one, but it also works in Internet Explorer 7 at non-default zoom levels:
<head>
    <style>
        #flying {
            position: fixed; 
        }
    </style>

    <script>
            // always return 1, 
            // except at non-default zoom levels in IE before version 8
        function GetZoomFactor () {
            var factor = 1;
            if (document.body.getBoundingClientRect) {
                    // rect is only in physical pixel size in IE before version 8 
                var rect = document.body.getBoundingClientRect ();
                var physicalW = rect.right - rect.left;
                var logicalW = document.body.offsetWidth;

                    // the zoom level is always an integer percent value
                factor = Math.round ((physicalW / logicalW) * 100) / 100;
            }
            return factor;
        }

        function UpdateFlyingObj (event) {
            var mouseX = event.clientX;
            var mouseY = event.clientY;

            if (navigator.appName.toLowerCase () == "microsoft internet explorer") {
                    // the clientX and clientY properties include 
                    // the left and top borders of the client area
                mouseX -= document.documentElement.clientLeft;
                mouseY -= document.documentElement.clientTop;

                var zoomFactor = GetZoomFactor ();
                if (zoomFactor != 1) {  // IE 7 at non-default zoom level
                    mouseX = Math.round (mouseX / zoomFactor);
                    mouseY = Math.round (mouseY / zoomFactor);
                }
            }


            var flyingObj = document.getElementById ("flying");
            flyingObj.style.left = mouseX + "px";
            flyingObj.style.top = mouseY + "px";
        }
    </script>
</head>
<body onmousemove="UpdateFlyingObj (event);">
    <div style="height:1000px;">
        The flying object also works for document scrolling.
    </div>

    <img id="flying" src="flying.gif" />
</body>

The previous two examples do not work in Internet Explorer 6, since it does not support fixed positioned elements. If you need an example that works in IE6, too, please see the pages for the clientX and clientY properties.

No Comments

2 Trackbacks

  1. Tweets that mention IE7 zoom level problem, where is the mouse pointer? « Dottoro -- Topsy.com
  2. Pointer