Sunday, May 09, 2010

Customize Android Browser Scaling with target-densityDpi

It was hard to find this little gem, so I thought I'd share it with the world: the Android team has implemented a custom meta viewport property to allow you to customize browser scaling for high resolution (HDPI) screens, like the WVGA 480x854 Motorola Droid and 480x800 Nexus One. [This is as opposed to medium resolution (MDPI) HVGA 320x480 T-Mobile G1 or myTouch 3G.]

You can use it like this, for example: <meta name="viewport" content="width=device-width, target-densityDpi=device-dpi">

What's Browser Scaling?

Here, ppk explains why a pixel is not a pixel. The CSS "px" unit may differ from a device's actual pixels, as the browser "scales" images and fonts to a larger size than you requested. (The browser just naturally assumes you didn't really mean "pixels" when you said "px," and helpfully tries to resize your content to make it readable on high-resolution phone screens.)

The Nexus One and Motorola Droid (and any other WVGA devices) will scale pixels even if you use the <meta name="viewport"> tag to instruct it not to do this. Worse, they using a non-integer scaling factor (e.g. 1.5x zoom, to scale 320px to 480px) which makes images look really weird.

target-densityDpi to the rescue!

Use this new undocumented <meta name="viewport"> property: target-densityDpi. The only existing documentation is in the Android check-in comment:

Add dpi support for WebView.

In the "viewport" meta tag, you can specify "target-densityDpi".
If it is not specified, it uses the default, 160dpi as of today.
Then the 1.0 scale factor specified in the viewport tag means 100%
on G1 and 150% on Sholes. If you set "target-densityDpi" to
"device-dpi", then the 1.0 scale factor means 100% on both G1 and Sholes.

Implemented Safari's window.devicePixelRatio and css media query

So if you use "device-dpi" and modify the css for font-size and image
src depending on window.devicePixelRatio, you can get a better page on

Here is a list of options for "target-densityDpi".

device-dpi:    Use the device's native dpi as target dpi.
low-dpi:       120dpi
medium-dpi:    160dpi, which is also the default as of today
high-dpi:      240dpi
<number>:      We take any number between 70 and 400 as a valid target dpi.

Fix http://b/issue?id=2071943

So how do I use it?

Like this, for example: <meta name="viewport" content="width=device-width, target-densityDpi=device-dpi">

You may also want to add the "user-scalable=no" property to prevent the user from zooming in/out and to guarantee that your images are exactly as you designed them. You can read more about other viewport properties in Apple's documentation which originally defines the


TabAtkins said...

Random note:

"(The browser just naturally assumes you didn't really mean "pixels" when you said "px," and helpfully tries to resize your content to make it readable on high-resolution phone screens.)"

You *don't* really mean "pixels" when you say "px", unless you really think that, in the future when we all have 1000dpi screens, today's 1024px-wide websites are *supposed* to be an inch wide.

The CSS px is an absolute length unit equal to 1/96 of an inch. (Or, equivalently, the CSS in unit is a device-relative unit equal to 96 px. Whatever happens to be easier to calibrate towards on your device.)

Richard said...

Brilliant. Thanks for your research!
Combining this with em units instead of px in CSS helps to equalize environments with the handsets I'm testing with (Motorola Droid and iPhone4)

Dermot said...

so glad I found this.
I kept having to use 2/3 height and width in my style sheets and I could never figure out why. Now I know.


Unknown said...

Thanks! Works perfectly in the native browser but on opera mobile it doesn't work yet

Shamick P. Gaworski said...

If this work, you just made my day/week. Thanks so much!!!!

John Aspinall said...

Wouldn't setting the property maximum-scale=1 in the meta viewport tag just stop the browser from scaling the viewport and solve this problem?

OMA said...

Thanks, this is just what I needed!

Henzo said...

Thanks! Solved my problem!