Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you get the CSS pixel / device pixel ratio?

I want to find the ratio between CSS pixels and device pixels.

Edit: I should have realized that this is just zoom level. I've added an answer to the canonical reference on zoom levels.

CSS pixels are the unit we use for almost everything--it's what element.style.width, element.clientWidth, element.offsetWidth etc. mean. Device pixels are the pixels that the browser actually paints to. A few properties are measured in device pixels, e.g. window.screen.width, which is the screen size (e.g. 1024) that doesn't change when the user zooms in.

Motivation: when the user zooms in, I want to increase a canvas's width and height (while keeping style.width and style.height the same CSS pixel value), scale() the context, and redraw on a crisper upscaled canvas.

I've read Quirksmode's A Tale of Two Viewports and High DPI on Surfin' Safari, but neither of them say how to get the ratio. The only ideas I have so far are to collect mousemoves and measure change in event.clientX divided by change in event.screenX, or to programatically create media queries using moz--min-device-pixel-ratio, use getComputedStyle() to test whether the rule matched, and narrow it down with a binary search. I hope there's a easier/more reliable way.

Edit: I've tried using the @media (-webkit-min-device-pixel-ratio:1) queries with Chrome, Safari, and Firefox 4, and apparently Webkit treats the property as a constant device pixel to screen pixel ratio (which doesn't change with zoom), whereas Firefox 4 treats it as device pixel to CSS pixel ratio (which increases when you zoom in). So in Firefox 4, I can discover the CSS pixel / device pixel ratio using a binary search, but not with Webkit.

like image 804
yonran Avatar asked Feb 21 '11 07:02

yonran


People also ask

How do you find the pixel ratio of a device?

Dividing the physical ppi by the ideal ppi of 150, gives the device pixel ratio.

What is CSS pixel ratio?

Put plainly, CSS pixel ratio (also referred to as device pixel ratio) is the relation between a device's physical pixels and logical pixels. Especially with the advent of retina screens, the pixel resolution of modern mobile devices is growing at a fast rate.

How do you measure pixels in CSS?

The CSS Pixel Device-Width can be calculated by dividing the Pixel Width by the CSS Pixel Ratio, and rounding it to the nearest integer.


4 Answers

You can use window.devicePixelRatio in Webkit based browsers to get the device pixel ratio directly in JavaScript. I have used this on Google Chrome, Android browsers (2.2+) and Mobile Safari. I have no idea about other browsers though.

like image 193
Tanzeel Kazi Avatar answered Oct 04 '22 18:10

Tanzeel Kazi


You can always use the following method and it would work in all the browsers

window.getDevicePixelRatio = function () {
    var ratio = 1;
    // To account for zoom, change to use deviceXDPI instead of systemXDPI
    if (window.screen.systemXDPI !== undefined && window.screen.logicalXDPI       !== undefined && window.screen.systemXDPI > window.screen.logicalXDPI) {
        // Only allow for values > 1
        ratio = window.screen.systemXDPI / window.screen.logicalXDPI;
    }
    else if (window.devicePixelRatio !== undefined) {
        ratio = window.devicePixelRatio;
    }
    return ratio;
};
like image 35
abhinav sharma Avatar answered Oct 04 '22 18:10

abhinav sharma


There is a much better CSS/JS solution:

/** sample media query for pixel-ratio=2" **/
@media  
(-webkit-min-device-pixel-ratio: 2), 
(min-resolution: 192dpi) { 
  .pixel-ratio-holder:before {
   content: "2";
  }
}


function jsPixelRatio(){
   return window.getComputedStyle(document.querySelector('.pixel-ratio-holder'), 'before').getPropertyValue('content').replace(/[^a-z]/g,'') * 1;
}
like image 31
androidavid Avatar answered Oct 04 '22 17:10

androidavid


How to get device Pixel Ratio

This example uses window.devicePixelRatio as a starting point AND also window.matchMedia() Web API as a fallback calculation.

The browser support for both those features is pretty good, so this should work great for most of use cases.

Here is a function that retrieves this information, originally written by PatrickJS and published as a GitHub Gist:

function getDevicePixelRatio() {
    var mediaQuery;
    var is_firefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;

    if (window.devicePixelRatio !== undefined && !is_firefox) {
        return window.devicePixelRatio;
    } else if (window.matchMedia) {
        mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
          (min--moz-device-pixel-ratio: 1.5),\
          (-o-min-device-pixel-ratio: 3/2),\
          (min-resolution: 1.5dppx)";
        if (window.matchMedia(mediaQuery).matches) {
            return 1.5;
        }
        mediaQuery = "(-webkit-min-device-pixel-ratio: 2),\
          (min--moz-device-pixel-ratio: 2),\
          (-o-min-device-pixel-ratio: 2/1),\
          (min-resolution: 2dppx)";
        if (window.matchMedia(mediaQuery).matches) {
            return 2;
        }
        mediaQuery = "(-webkit-min-device-pixel-ratio: 0.75),\
          (min--moz-device-pixel-ratio: 0.75),\
          (-o-min-device-pixel-ratio: 3/4),\
          (min-resolution: 0.75dppx)";
        if (window.matchMedia(mediaQuery).matches) {
            return 0.7;
        }
    } else {
        return 1;
    }
}

CanIUse: window.devicePixelRatio, Window.matchMedia()

Useful links: MDN - window.devicePixelRatio, MDN - Window.matchMedia()

like image 37
Andrii Verbytskyi Avatar answered Oct 04 '22 18:10

Andrii Verbytskyi