Mobile web: how to get physical pixel size?
I am creating a web app using jQuery Mobile and PhoneGap. There is a graph and if the user is using a large screen, I would like to display more points on this graph, because points are tappable and the shouldn't be too close (physically).
For example: if someone has an iPhone, I want to display N points on the line graph. If he has an iPad, i want to display 2xN points (cause iPad has physically larger screen), but if he has some newer Android phone that is physically small like an iPhone but has a screen with many pixels (like an iPad), I want to display N points, because the points are physically small (and closer together).
So is there a way to get this data? An alternative is determining whether the device is a tablet.
Solution 1:
This issue is a complex one.
You can find out the screen resolution of your device in JavaScript by using screen.width and screen.height, just like you would on a Desktop.
However, on a mobile device 1 CSS pixel will not necessarily have a 1 : 1 proportion with a physical screen pixel. Let's say your screen.width returns a value of 640 pixels. If you add a banner that is exactly 640 pixels wide, it will most likely go over the available screen width of your phone.
The reason for that is that mobile manufacturers set the device's default viewport for a different scale factor than your device's screen. That is so the contents of webpages that were not designed specifically for mobile devices would still appear legible without the need for pinch zooming.
If you use the meta viewport tag, you can set the scale factor of your viewport to a 1 : 1 ratio, by setting its width value to the device's width value, like so:
<meta name="viewport" width="device-width" content="target-densitydpi=device-dpi" />
Now that 640 pixels banner would fit exactly on your 640 pixels screen.
Unfortunately as of this moment, as far as I'm aware, there is no real way to tell the actual physical screen size (as in inches or mm) of the device displaying your web content. At least not in JavaScript. Although the browser can access some useful information such as device.name or device.platform, you cannot tell how many inches or mm those 640 pixels represent, unless you know in advance the measurements of a given device's screen.
To me it's pretty obvious why someone would want a version of an app for small phone screens, and another larger tablet screens. Small buttons, for instance. Sometimes they are so close together that your finger would cover two at once. At the same time you wouldn't want those fat buttons designed for mobile screens showing on a nice 10'' tablet.
You could of course with the help of screen.width and window.devicePixelRatio find out if you are running, say, on an iPhone retina or an iPad 2, but when you start considering the myriad of screen resolutions and pixel densities on Android devices, the task becomes nearly impossible.
The solution is going Native.
On Android, you can use the code at the following thread to figure out if your app is running on a large screen:
Tablet or Phone - Android
You can then use the code on this other thread to query your wrapper app from JavaScript, using PhoneGap:
Communication between Android Java and Phonegap Javascript?
With Apple, it's even more straight forward:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
//running on an iPad
}
else {
//iPhone or iPod
}
And if you use the same naming convention for your Android and Apple objects, your code will still be universal, which is the whole point of PhoneGap. For instance, in my case I used the same names for both my Java and my Objective-C objects and methods. In JavaScript I just need to call:
window.shellApp.isTabletDevice();
And my code runs and looks nice on every size of screen.
Solution 2:
What you want is to check the device's pixel density - measured in DPI - as @Smamatti already mentioned you control this with CSS media queries.
Here's an article on how to cope with varying DPIs and screen sizes, using those CSS media queries.
UPDATE: here's the javascript function (from the above link) that uses a trick to figure out the current device DPI:
function getPPI(){
// create an empty element
var div = document.createElement("div");
// give it an absolute size of one inch
div.style.width="1in";
// append it to the body
var body = document.getElementsByTagName("body")[0];
body.appendChild(div);
// read the computed width
var ppi = document.defaultView.getComputedStyle(div, null).getPropertyValue('width');
// remove it again
body.removeChild(div);
// and return the value
return parseFloat(ppi);
}
Hope this helps!