58

Is there a way to access the screen display's DPI settings in a Javascript function?

I am trying to position a HTML panel on the page and when the user's DPI is set to large (120), it throws the position off. I need to be able to know what the DPI is so I can adjust the position accordingly.

Rémi Becheras
  • 14,902
  • 14
  • 51
  • 81
Yttrium
  • 2,057
  • 7
  • 25
  • 28

4 Answers4

45

Looks like you can use the 'screen' DOM object in IE, its got properties for deviceXDPI, deviceYDPI, logicalXDPI, logicalYDPI.

https://www.w3schools.com/jsref/obj_screen.asp

Here's a solution from http://www.webdeveloper.com/forum/showthread.php?t=175278 (i havent tried it, seems like a total hack :) Just create something 1 inch wide and measure it in pixels!

console.log(document.getElementById("dpi").offsetHeight);
#dpi {
    height: 1in;
    left: -100%;
    position: absolute;
    top: -100%;
    width: 1in;
}
<div id="dpi"></div>
Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • 25
    http://jsfiddle.net/AvVH4/ has this code. It always returns 96 for me. – thugsb Jul 14 '11 at 18:02
  • 4
    This codes returns the "DPI setting" from Windows's display properties, i.e. 96="Normal size", 120="Large size", or other values for custom setting, such as 106="110% of normal size". – Julien Kronegg Jul 23 '12 at 09:46
  • Seems to work under MS Windows, but not on some mobile devices, see http://stackoverflow.com/q/279749/698168 – Julien Kronegg Jul 23 '12 at 09:56
  • 5
    Doesn't seem to be working. The jsfiddle returns 96 on my iPhone5S. – neoneye Apr 03 '14 at 15:20
  • 3
    It doesn't work. Don't do it. I just tried it on my test system with 200% DPI setting and neither IE nor Chrome reported it correctly. Both gave me 96. – c00000fd Aug 29 '14 at 19:33
  • Take a look at this improved solution http://stackoverflow.com/a/26004882 which takes the devicePixelRatio in account. Worked for me. – RiZKiT Feb 15 '15 at 21:10
  • I think almost nobody targets IE, for it is always odd. – Mohammed Shareef C Jun 13 '17 at 06:48
  • 1
    Here, an inch is defined as 96 px, so no matter what your screen size/resolution it will always return 96. – GreySage Jun 22 '17 at 19:14
  • 3
    This is inaccurate. An `in` unit in CSS will always be 96 px on a screen, no matter the DPI. It's a unit only really useful for print. Source https://www.w3.org/Style/Examples/007/units.en.html – Perry Jun 27 '18 at 15:41
  • This does not work for me – OG Sean Jul 16 '22 at 23:25
37

Firstly, to help with the possible (and very common) confusion with the term DPI (dots per inch):

DPI isn't exactly a part of "display settings". It's (mis)used in two different contexts:

  1. The native pixels per inch of a display (or video). It determines how small the pixels are. You can have the same 1024x768 resolution on both a 14" laptop screen and a 17" LCD monitor. The former would roughly be 1280/14 = 91 DPI and the latter would roughly be 1280/17 = 75 DPI. The DPI of a screen is immutable; it can't be changed with display settings. More...
  2. The dots per inch painted on paper during printing. This is the number of side-by-side dots a printer/photocopier/fax machine can imprint within an inch of paper. Most printers can be set to print at a lower DPI, by just printing each dot as two, four, etc. dots. More...

When printing an image, there are many things that affect the final dimensions of the image on paper:

  • The dimensions of the source image -- this is the amount of pixels or data there is.
  • The DPI of the source image. This value determines how the dimensions should be interpreted when printing the image.
  • If the source image doesn't have embedded DPI information (a JPEG can have one, a GIF never does), the program that's being used may have settings to specify a DPI. This could be an image viewer/editor or even a web browser.
  • The zoom factor that's typically specified in a print dialog.
  • The current DPI setting of the printer.
  • The physical (max) DPI of the printer.

The bottom line is, the image that you're printing will effectively get resampled (reduced or enlarged) to match the final DPI that's used in the print process. Any of the parties involed may be causing this (the program, the print driver, the printer).

Now, coming back to your question. No, you can't determine the DPI of the screen, because it's not in software domain. It's a hardware domain term, describing how large a monitor a user could afford to buy. Update: I initially wrote this answer back in 2009, with my understanding of the current technologies. As @thure pointed out, you can now (since 2012?) use the window.matchMedia function to determine the DPI of the screen.

If you're trying to achieve precision in printing an HTML layout, as others have suggested, your CSS should use print dimensions like em, pt or pc instead of px. However, the final outcome might still depend on the browser using. If converting your HTML to PDF (or generating PDF from scratch) is an option for you, printing a PDF would give you the truest WYSIWYG both on screen and paper.

Charlie
  • 11,380
  • 19
  • 83
  • 138
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • 2
    Although you can't change the physical DPI, you *can* change the software which maps measurements to pixels, which is governed by software, which, has a arbitrary value, usually probed from the monitor via EDID, but can be overridden. Which is what I think the OP was getting at. – Kent Fredric Jan 26 '09 at 05:38
  • 36
    No, there are many cases where knowing physical properties like DPI and screen dimensions from software--including from as high a level as Javascript--is useful. API designers who don't expose something this obvious because they can't think of a case where it's needed must both lack foresight and have delusions of omniscience. – Glenn Maynard Nov 28 '10 at 23:25
  • 1
    @Glenn Maynard: Yes, in fact, Android supports DIP (device-independent pixels) in its graphics API. The lower level rasterization library translates DIPs to actual pixels based on the known DPI of the screen. – Ates Goral Nov 29 '10 at 04:29
  • This answer is essentially wrong: "No, you can't determine the DPI of the screen, because it's not in software domain," is simply not true. You could use the matchMedia function or the screen object mentioned in @Ryan's answer. – Will Mar 07 '13 at 00:12
  • 1
    @thure I wasn't aware of a `matchMedia` function back in 2009 when I wrote this answer. The answer might be a bit outdated and thus become inaccurate today. I'll update it to mention the function. Thanks for raising this. – Ates Goral Mar 07 '13 at 03:37
  • 1
    Update: although `matchMedia` allows for querying dpi, most browsers will assume 96dpi regardless of the actual pixel density of the display. – Will Mar 20 '13 at 16:57
  • @thure, it's probably because browsers running on desktops have no way of knowing the screen DPI. There probably needs to be an OS-level facility for carrying this information (based on monitor driver, etc.) to the browser. I emphasize: Probably. I really haven't kept myself up-to-date with the offerings of modern OS APIs. Mobile phone browser can do this because it is easier to know the DPI of the phone screen (especially since people don't typically attach external displays to phones :)). – Ates Goral Mar 20 '13 at 18:13
  • @AtesGoral, I would guess the same, though apparently webkit and gecko know their "pixel density" via media queries, which is a similar metric to dpi - no idea where the user agents get that information, though. – Will Mar 21 '13 at 00:04
  • In short, currently there is no means to know the system dpi (72 or 96) and the screen resolution from within a browser using javascript. Is that correct? – Mohammed Shareef C Jun 13 '17 at 06:45
  • if (window.matchMedia("(min-resolution: 192dpi)").matches) console.log('matches!') works fine for me, I am using a 2 screen set up, if I run it on my macbook screen it prints 'matches!', but not if i drag the window over to my crappy old monitor – Nodeocrat Nov 02 '18 at 11:19
  • How are they doing this here and getting the size of the screen in inches and pixels: https://dpi.lv/ – OG Sean Jul 16 '22 at 23:28
35

You might use the window.devicePixelRatio property to get the scaling ratio of the screen/page. This works well in current IE, Edge, Chrome and Firefox on the desktop (Windows), but it doesn't seem to be a current standard. It returns 1 on my desktop PC with a conventional monitor and 2 on the Surface with 200% scaling. Values should range from 1.0 to 3.0 these days. I could use this to correct dynamic image serving size to provide sharper images on high-resolution screens.

If you need some logical dpi/ppi, multiply that value with 96. It won't be the actual physical ppi though, just what the OS treats it like.

chojnicki
  • 3,148
  • 1
  • 18
  • 32
ygoe
  • 18,655
  • 23
  • 113
  • 210
2

There isn't a way that I know of, however, they may be an alternative solution:

Specify your measurements in 'pt' and 'em', which are screen relative metrics.

http://www.w3schools.com/cssref/css_units.asp

https://css-tricks.com/the-lengths-of-css/

  • em:
    1em is equal to the current font size. 2em means 2 times the size of the current font. E.g., if an element is displayed with a font of 12 pt, then '2em' is 24 pt. The 'em' is a very useful unit in CSS, since it can adapt automatically to the font that the reader uses
  • pt:
    point (1 pt is the same as 1/72 inch)
  • pc:
    pica (1 pc is the same as 12 points)
Goose
  • 4,764
  • 5
  • 45
  • 84
Kent Fredric
  • 56,416
  • 14
  • 107
  • 150
  • Try this one. http://www.w3schools.com/cssref/css_units.asp – Sam Oct 28 '13 at 03:09
  • 9
    `1pt = 1.33px` and `1pc = 16px`. Regardless of dpi, as browsers assume `1in = 96px`, which is not real and incorrect... – Ωmega Dec 13 '13 at 14:12