[click on image to start to the interactive demonstration]

realDPI
Finding the physical screen resolution by using moiré patterns
Try the demonstration here: https://xyzzy.github.io/realDPI/
Welcome to the Wonderful broken World of browser DPI.
when you see things the browser doesn’t
Visual DPI tester.
Real DPI
Visually detect our browsers real screen resolution and DPI.
Browsers have broken the internet. Instead of making available their real resolution and DPI, they spoof the DPI to the self-proclaimed “standard” of 96 dots per inch.
The hack effectively changes your high-resolution and flagship expensive screen to something like 384x854
Why is this a problem
Browser coordinates used to position page elements are floating point. This scales for any screen size and this spoofing is generally invisible.
The problem arises with procedural generated content, specifically <canvas> in combination with context2d.putImageData() which is integer based.
To compensate you need to oversample the canvas. MDN suggests https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio using window.devicePixelRatio.
In theory window.availableWidth/Height times window.devicePixelRatio should be the physical pixel size, only experience reveals this is seldom the case.
Why this page
Browsers lie, hide and conceal the physical pixel size of your screen. However, carefully constructing the canvas can produce moiré effects when down sampled. The patterns give visual hints to determine the actual size.
The CSS standard has sadly botched the meaning of DPI by fixating it to being 96 on any screen on any device.
Browser builders have tried to compensate this by introducing window.devicePixelRatio.
Sadly, even that does not always reveal reality.
There is currently no way to get any physical screen measurements or real DPI using javascript.
Observations
Firefox desktop (4K screen):
- 4K has
availWidth/Heightof 3840x2160 with pixelRatio=1. - With full screen,
clientHeightis one less for the historical hidden menu bar/line. - Resizing with ctrl +/- keeps
clientWidthandavailWidthidentical.
Chrome desktop (4K screen)
- 4K has
availWidth/Heightof 2560x1440 withpixelRatio=1.125. - Resizing with ctrl +/- keeps
availWidthconstant and changesclientWidth/pixelRatio. clientWidth/Heightdoes not matchavailWidth/Height.- To get a 4K
clientWidth/Heightyou need toctrl-. Browser then reportsavailWidth/Heightof 2560*1440 andpixelRatio=1.
Firefox mobile (1440x2560 screen)
- 1440x2560 has
availWidth/Heightof 360x640 withpixelRatio=4. clientWidth/Heightdoes not matchavailWidth/Height.- Additionally, portrait has
clientWidth/Height980x1524 (that about 68% of available). - Additionally, landscape has
clientWidth/Height980x551 (that about 38% of available).
Chrome mobile (1440x2560 screen)
- 1440x2560 has
availWidth/Heightof 360x640 withpixelRatio=4.
Further reading
https://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html
https://daringfireball.net/2010/04/why_960_by_640
https://fronteers.nl/congres/2012/sessions/a-pixel-is-not-a-pixel-peter-paul-koch
Source code
Grab one of the tarballs at https://github.com/xyzzy/realDPI/releases or checkout the latest code:
git clone https://github.com/xyzzy/realDPI.git
Versioning
This project adheres to Semantic Versioning. For the versions available, see the tags on this repository.
License
This project is licensed under Affero GPLv3 - see the LICENSE.txt file for details.