Getting the physical screen dimensions / dpi / pixel density in Chrome on Android
You can't really get the real physical dimensions or the actual DPI and even if you could, you can't do anything with them.
This is a pretty long and complex story, so forgive me.
The web and all browsers define 1px as a unit called a CSS pixel. A CSS pixel is not a real pixel, rather a unit that is deemed to be 1/96th of an inch based on the viewing angle of the device. This is specified as a reference pixel.
The reference pixel is the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm's length. For a nominal arm's length of 28 inches, the visual angle is therefore about 0.0213 degrees. For reading at arm's length, 1px thus corresponds to about 0.26 mm (1/96 inch).
In 0.26mm of space we might have very many real device pixels.
The browser does this mainly for legacy reasons - most monitors were 96dpi when the web was born - but also for consistency, in the "old days" a 22px button on a 15 inch screen at 800x600 would be twice the size of a 22px button on a 15 inch monitor at 1600x1200. In this case the DPI of the screen is actually 2x (twice the resolution horizontally but in the same physical space). This is a bad situation for the web and apps, so most operating systems devised many ways to abstract pixel values in to device independent units (DIPS on Android, PT on iOS and the CSS Pixel on the web).
The iPhone Safari browser was the first (to my knowledge) to introduce the concept of a viewport. This was created to enable full desktop style applications to render on a small screen. The viewport was defined to be 960px wide. This essentially zoomed the page out 3x (iphone was originally 320px) so 1 CSS pixel is 1/3rd of a physical pixel. When you defined a viewport though you could get this device to match 1 CSS pixel = 1 real pixel at 163dpi.
By using a viewport where the width is "device-width" frees you up from having to set the width of the viewport on a per device basis to the optimal CSS pixel size, the browser just does it for you.
With the introduction of double DPI devices, mobile phone manufacturers didn't want mobile pages to appear 50% smaller so they introduced a concept called devicePixelRatio (first on mobile webkit I believe), this lets them keep 1 CSS pixel to be roughly 1/96th of an inch but let you understand that your assets such as images might need to be twice the size. If you look at the iPhone series all of their devices say the width of the screen in CSS pixels is 320px even though we know this is not true.
Therefore if you made a button to be 22px in CSS space, the representation on the physical screen is 22 * device pixel ratio. Actually I say this, it is not exactly this because the device pixel ratio is never exact either, phone manufacturers set it to a nice number like 2.0, 3.0 rather than 2.1329857289918....
In summary, CSS pixels are device independent and let us not have to worry about physical sizes of the screens and the display densities etc.
The moral of the story is: Don't worry about understanding the physical pixel size of the screen. You don't need it. 50px should look roughly the same across all mobile devices it might vary a little, but the CSS Pixel is our device independent way to build consistent documents and UI's
Resources:
- https://developers.google.com/web/fundamentals/layouts/rwd-fundamentals/set-the-viewport
- https://developers.google.com/web/fundamentals/layouts/rwd-fundamentals/size-content-to-the-viewport
- http://viewportsizes.com/
- http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html
- http://en.wikipedia.org/wiki/Device_independent_pixel
- http://www.w3.org/TR/css3-values/#absolute-lengths
- https://developer.mozilla.org/en/docs/Mozilla/Mobile/Viewport_meta_tag
Based on Matanster's answer in which he observed SVG properties such as screenPixelToMillimeterX
, I made a test to see if they work:
(EDIT: these properties are deleted (or never were) from spec, and browsers may no longer have (or never had) them, moving us further away from ever knowing actual physical display sizing).
// on Macbook Pro Retina (2880x1800, 15.4"), is the calculated diagonal size
// approximately 15.4? Let's see...
var svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var screenWidthMillimeters = svgEl.screenPixelToMillimeterX * 2880;
var screenHeightMillimeters = svgEl.screenPixelToMillimeterY * 1800;
var screenDiagonalMillimeters = Math.sqrt(Math.pow(screenWidthMillimeters, 2) + Math.pow(screenHeightMillimeters, 2)); // pythagorean theorem
var screenDiagonalInches = (screenDiagonalMillimeters / 10 / 2.54); // (mm / 10mm/cm) / 2.54cm/in = in
console.log("The calculated diagonal of the screen is "+screenDiagonalInches+" inches. \nIs that close to the actual 15.4\"?");
This is the output:
The calculated diagonal of the screen is 35.37742738560738 inches.
Is that close to the actual value of 15.4?
Nope.
There seems to be no way to get real physical values in a web browser yet.
You can create any page element and set its width using real physical units. For example
<div id="meter" style="width:10cm"></div>
And then get its width in pixels. For example html code below (i used JQuery) shows device screen width in centimeters
<script>
var pixPer10CM = $('#meter').width();
var CMPerPix = 10 / pixPer10CM;
var widthCM = screen.width * CMPerPix;
alert(widthCM);
</script>