Browser compatibility — viewports

Related files:

Opera Mobile
Opera 10 on Nokia N8
Opera 10 on HTC Touch Pro
Opera 10.1b on Android 2.2 (Nexus One)
Opera Mini
5 on Nokia E71 (Symbian), BlackBerry 9500
iPhone
Safari on iPhone 3.1.3 (3G)
Android
Android 2.2 WebKit on Nexus One and 2.1 on HTC Legend
Symbian
on E71 (version 1), E72 and N97 (version 2), and N8 (version 3).
S40
on Nokia 7230 and X3-02
Dolfin
Dolfin WebKit on Samsung Wave (bada)
BlackBerry
BlackBerry WebKit on BB Torch (OS6)
Palm
Default browser on Palm Pre 2
Phantom
Default browser on LG GD880 Mini
Obigo WebKit
Default browser on HTC Smart (Brew)
Bolt
1.6 on Nokia E71
MicroB
Nokia N900 default browser
Firefox
Firefox 4b3 on Android (Nexus One)
IE
IE Mobile 6 on HTC Touch Pro
BlackBerry old
Default browser on BlackBerry 9000 (Bold) and 9500 (Storm)
NetFront
NetFront 4 beta on HTC Touch Pro
Obigo
7.3 on undisclosed device

Last major update on 17 February 2011.

Here’s the inevitable compatibility table that goes with my viewport research. It treats the viewports themselves as well as some related items.

Definitions

See A tale of two viewports for a further explanation of these terms.

CSS pixels
Expand and contract with zooming; it’s this pixels that are taken as measurement grid for all CSS declarations.
Device pixels
Formal number of pixels on device. Generally useless to web developers.
Layout viewport
The initial area of the HTML element. CSS declarations such as width: 20% are calculated relative to this viewport. Is usually quite a bit wider than the visual viewport.
Visual viewport
The actual screen viewport through which you look at the layout viewport.

Properties

This table looks into the properties that are necessary to read out useful information about the two viewports. As you can see, some of them are a mess and others are very well supported.

Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko
screen.width and screen.height

Screen resolution in device pixels. Should change when the orientation of the device is changed.

Almost Yes Incomplete Yes HTML or layout Yes Incomplete Layout Yes Don’t know Yes Yes Incomplete Incorrect

Note that this resolution is almost completely useless to web developers. If it’s too small, people will want to zoom in anyway.

HTML
Browser returns dimensions of the <html> element in CSS pixels.
Layout
Browser returns dimensions of the layout viewport in CSS pixels.
  • Opera Mobile on Windows Mobile always gives the portrait sizes. Opera Mobile on Symbian handles everything correctly.
  • Safari iPhone, Palm WebKit, and Obigo (old) always give the portrait sizes.
  • NetFront always gives the landscape sizes.
  • Dolfin reports the size of the layout viewport if a <meta viewport> tag is applied to the page; the size of the <html> element otherwise.
  • UCWeb gives 800x600 on an iPhone 3G. Obviously way wrong.
  • I do not understand Bolt’s values.

I test Opera Mobile, IE, and NetFront on the same Windows Mobile device. The Opera and NetFront problems are thus not device-related: IE gets it right on the same device.

window.innerWidth and window.innerHeight

Dimensions of the visual viewport in CSS pixels.

screen Yes layout Yes HTML or layout Yes layout Yes layout screen layout No v 4.7 layout Don’t know Incorrect
Screen
Browser returns screen dimensions in device pixels.
Layout
Browser returns dimensions of the layout viewport in CSS pixels.
HTML
Browser returns dimensions of the <html> element in CSS pixels.
  • BlackBerry supports this from 4.7 on.
  • Dolfin reports the size of the layout viewport if a <meta viewport> tag is applied to the page; the size of the <html> element otherwise.
  • I do not understand Obigo’s values.
Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko
documentElement. offsetWidth and documentElement. offsetHeight

Dimensions of the <html> element in CSS pixels.

Yes Yes Yes visual Yes Incorrect Yes Incorrect

The dimensions of the HTML element are still important because they’re sometimes used for other purposes, such as media queries.

Visual
Browser returns the dimensions of the visual viewport in CSS pixels.
  • NetFront gives the correct dimensions in zoom 100%. When you zoom it tries to keep the layout viewport at visual viewport width, but reports the <html> element’s dimensions wrong.
  • UCWeb returns 1x1.
documentElement. clientWidth and documentElement. clientHeight

Dimensions of the layout viewport in CSS pixels.

Yes Yes Visual HTML or Yes Yes HTML Yes Yes Incorrect No Incorrect Yes Incorrect
Screen
Browser returns screen dimensions in device pixels.
HTML
Browser returns dimensions of the <html> element in CSS pixels.
Visual
Browser returns dimensions of visual viewport in CSS pixels.
  • In Symbian WebKit 1 it’s the HTML element size. In version 2 it’s the visual viewport size.
  • Dolfin reports the size of the layout viewport if a <meta viewport> tag is applied to the page; the size of the <html> element otherwise.
  • IE gives 1024x768
  • NetFront’s readings are correct only at zoom 100%.
  • UCWeb returns 1x1.
pageXOffset and pageYOffset

Scrolling offset of the page in CSS pixels.

0 Yes Depends Yes 0 Depends Yes 0 0 Yes No 0 Yes 0
  • Dolfin reports the offset only if a <meta viewport> tag has been applied to the page.
  • Phantom reports the offset only if you set the <meta viewport> to device-width.
documentElement. scrollLeft and documentElement. scrollTop

Scrolling offset of the page in CSS pixels.

0 0 0 Yes Yes No 0 Yes 0

In practice you need these properties only for IE — just as on desktop.

Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko

A caution

Before we proceed, a caution. There is no official standard for any of this; I call a behaviour that makes sense and is supported by more browsers than any competing behaviour the “standard.” Any standard is better than no standard.

Besides, it’s not exactly easy right now to write cross-browser scripts because many properties give false information.

Let’s take the dimensions of the visual viewport as an example. This is by far the most important information because it tells us how much stuff the user actually sees.

Six browsers store the information in window.innerWidth/ Height. IE stores it in another property pair. The other twelve browsers just don’t give this information anywhere.

Worse, when you query window.innerWidth/ Height these twelve browser return the dimensions not of the visual viewport, but of the screen or the layout viewport — or pure gibberish.

That makes window.innerWidth/ Height rather hard to use at the moment. Even worse, we can’t find out whether window.innerWidth/ Height works or not; there is no useful JavaScript check we can do to validate the values a browser returns.

I kind of assume the other browser vendors will implement window.innerWidth/ Height as Apple, Nokia, and RIM did. We web developers badly need the data.

Measurements

With that caveat in mind, how does the previous table translate to getting the actual data you need? The table below details that.

Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko
Screen size

In device pixels. Useless in practice.

Almost Yes Incomplete Yes No Yes Incomplete No Yes No Yes Yes Incomplete No

Should be screen.width/height.

  • Opera Mobile on Windows Mobile always gives the portrait sizes. Opera Mobile on S60 handles everything correctly.
  • iPhone and Obigo old always give portrait sizes.
  • NetFront always gives landscape sizes.

I test Opera Mobile, IE, and NetFront on the same Windows Mobile device. The Opera and NetFront problems are thus not device-related: IE gets it right on the same device.

Visual viewport size

In CSS pixels.

No Yes No Yes No Yes No Yes No No Alternative Yes No

Should be window.innerWidth/Height.

  • IE stores this in document.documentElement.offsetWidth/Height.
Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko
Layout viewport size

In CSS pixels.

Yes Yes No Depends Yes No Yes No Yes No Incorrect No

Should be document.documentElement.clientWidth/Height.

  • NetFront’s readings are correct only at zoom 100%.
  • Dolfin: only when a <meta viewport> tag has been applied to the page.

Note: Some browsers (S40, Obigo WebKit) make the layout viewport and the <html> element narrower if the user zooms in. Thus they minimise the use of horizontal scrolling.

HTML element size

Actual size of the HTML element. In CSS pixels

yes yes yes Alternative yes Incorrect yes No

Should be document.documentElement.offsetWidth/Height.

  • IE stores it in document.body.clientWidth/Height instead.
  • NetFront’s readings are correct only at zoom 100%.
Offset of visual viewport

The scrolling offset of the visual viewport relative to the layout viewport

No Yes Depends Yes No Depends Yes No Yes Alternative No Yes No

Should be window.pageX/YOffset.

  • IE stores it in document.documentElement.offsetTop/Left. (So do MicroB and Obigo.)
  • Dolfin reports the offset only if a <meta viewport> tag has been applied to the page.
  • Phantom reports the offset only if you set the <meta viewport> to device-width.
Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko

Mouse coordinates

I left out the proxy browsers (Opera Mini, Bolt, UCWeb) because their lack of client-side interactivity makes reading out event coordinates pointless (not to mention very hard).

Property Opera Mobile iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Firefox MicroB IE Mobile BlackBerry old NetFront Obigo
Presto WebKit Gecko
clientX/Y

In CSS pixels, relative to the visual viewport

Incorrect page Yes page Yes page Yes page Yes screen page screen
screen
Returns coordinates relative to the visual viewport in device pixels.
page
Returns coordinates relative to the layout viewport in CSS pixels.
  • I don’t understand Opera’s values.
  • My Dolfin doesn’t support zoom, so I can’t really test this property. It gives the correct values at 100% zoom, but that doesn’t mean anything.
pageX/Y

In CSS pixels, relative to the layout viewport

10.1b Yes Yes No screen No
screen
Returns coordinates relative to the visual viewport in device pixels.
  • Opera 10.1b gets this one right. Earlier versions don’t.
screenX/Y

In device pixels, relative to the visual viewport

Incorrect Yes client Yes page Yes page client Yes
client
Returns coordinates relative to the visual viewport in CSS pixels.
page
Returns coordinates relative to the layout viewport in CSS pixels.
  • I don’t understand Opera’s values.
  • Obigo old defines the visual viewport minus the toolbars and such. That’s defensible.
Property Opera Mobile iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Firefox MicroB IE Mobile BlackBerry old NetFront Obigo
Presto WebKit Gecko

Opera Widget Manager: all three correct. Since there is no zoom, client is always equal to screen.

Media queries

Note: here I test whether the browser takes its width and height information from the correct source. Even if the source properties report wrong information, the media query support is still judged correct if it copies its information from the right properties.

Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko
device width/height

Uses screen.width/height.

Yes Yes Static Yes Yes No
@media all and (max-device-width: 400px) {
	// styles assigned when device width is smaller than 400px;
}
Static
Media queries don’t adapt when the screen is resized.
  • Symbian WebKit supports media queries from version 2 on.
width/height

Uses documentElement .clientWidth/Height.

Yes Yes Static Yes Almost Yes Yes No
@media all and (max-width: 400px) {
	// styles assigned when width is smaller than 400px;
}
Static
Media queries don’t adapt when the screen is resized.

Opera Mini: since innerWidth, clientWidth, and screen.width are the same, the two media queries will yield the same result.

  • On Android and Opera Mini and Nokia and MicroB innerWidth and clientWidth are the same (incorrectly).
  • In Firefox innerWidth and clientWidth are equal to screen.width (incorrectly)
  • Symbian WebKit supports media queries from version 2 on.
  • Obigo WebKit gets the height wrong. Not the width, though, and that’s what counts.
Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko

Meta viewport

Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko
Basics

Sets the dimensions of the layout viewport.

Yes No Yes No Yes Buggy Yes No Yes No Yes No Yes No
<meta name="viewport" content="width = 380">
<meta name="viewport" content="width = device-width">

Should narrow the layout viewport to the indicated width. The device-width should equal screen.width. It does not on the Nexus (2/3rds of screen). Likely, the new iPhone OS 4 will report 320px, which is half of the official screen size.

  • Opera Mobile 10.10 does not allow any zooming in pages with a <meta viewport>.
  • Phantom can’t handle values such as width=380. It usually makes the page 480px wide, but sometimes 744px. Go figure.

General Dolfin note: when a <meta viewport> is applied, screen.width/height, document.documentElement. clientWidth/Height and window.innerWidth/Height suddenly give the size of the layout viewport (which is correct for clientWidth/Height but not for the others). Besides, window.pageX/YOffset suddenly works correctly.

Change immediately

Change the tag directly after it’s been written into the page

Test page
Yes n/a Yes n/a Yes n/a To be tested n/a No n/a Yes To be tested n/a Yes n/a
<meta id="testViewport" name="viewport" content="width = 380">
<script>
var mvp = document.getElementById('testViewport');
mvp.setAttribute('content','width=480');
</script>
Change later

Change the tag once the page has been loaded

Test page
No n/a Yes n/a No Yes n/a To be tested n/a No n/a No To be tested n/a No n/a
<meta id="testViewport" name="viewport" content="width = 380">
<script>
window.onload = function () {
	var mvp = document.getElementById('testViewport');
	mvp.setAttribute('content','width=580');
}
</script>
Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko

Position fixed

position: fixed is a problem I describe in this blog post. Relative to which viewport is the element fixed?

Property Opera Mobile Opera Mini iPhone Android Symbian S40 Dolfin BlackBerry Palm Phantom Obigo Bolt Firefox MicroB IE Mobile BlackBerry old NetFront Obigo UCWeb
Presto WebKit Gecko
position: fixed

Test page

hopping layout layout depends Visual layout hopping hopping layout layout hopping No Gone hopping layout No
visual
Relative to visual viewport
layout
Relative to layout viewport
hopping
Relative to layout viewport, scrolls with page, and is re-positioned when scrolling stops.
  • Nexus One (2.2) does layout, while HTC Legend (2.1) does a sort of strange hopping. I’m not sure if the difference is between the Android versions or the browser vendor; could be both.
  • BlackBerry WebKit and the Android WebKit on HTC Legend try to do hopping, but get confused when the user zooms.
  • Palm WebKit hops, but once the layer hops it disappears.
  • Dolfin changes to hopping when you apply a <meta viewport> to the page.
  • NetFront tries hopping but gets the position wrong (too low).
  • The layer doesn’t show up at all in BlackBerry old.