In a sensible world, determining web browser orientation on mobile and tablet devices should be as straight forward as querying a property such as
window.orientation and hoping for a value such as
landscape to get returned. Unfortunately, the harsh reality of current API’s and web browser inconsistencies makes the process way more complicated than it should be.
This post takes a look at the current methods available to web developers to determine browser orientation, and details some of the problems found along the way.
window.orientation is supported on iOS and by the majority of Android devices on the market today. When queried, the property will return a number based on the degrees of rotation from a device’s default orientation.
Unfortunately, there are a lot of common misconceptions about what these values represent. For example, a value of
0 degrees does not necessarily mean
portrait, as it depends on which orientation is considered to be default by the manufacturer. Some tablet browsers, such as the iPad, will use
0 for portrait. Some Android tablets, such as the Xoom, use
0 for landscape.
I have seen certain mobile web frameworks fall at this first hurdle, by assuming all browsers and devices share the same implementation as iOS Safari. It is the framework assumptions here that are at fault, not the browser implementation.
So just how do we check if a device is being held in portrait or landscape? We could just check
window.innerHeight when the
orientationchange event fires, right?
Well, sadly no…
Here come the Android quirks
Unfortunately, some Android browsers seem to fire
orientationchange before the window
resize event, so checks for
window.innerHeight can be reported incorrectly on some devices. A
setTimeout can help, but it is not really reliable as the time it takes for these values to change seems to vary from device to device.
The next alternative is to use the window
resize event instead. This will surely work reliably, right? Well yes, kind of. But with another inevitable Android catch:
Android 4.x stock browser fires
resize whenever the on-screen keyboard is shown. Depending on the height of the keyboard and size of screen, this can result in
window.innerWidth being greater than
window.innerHeight, causing in an incorrect orientation to be reported. In order to combat this
resize event triggering an unwanted change in orientation, it is necessary to store the previous orientation and check that
window.innerWidth has actually changed. If only
window.innerHeight changes, then the keyboard is likely visible.
CSS Media Queries and window.matchMedia
As a side note, this
resize event behavior on Android 4.x stock browser will also trigger CSS orientation media queries, such as:
This can lead to unintentional styles being applied when the keyboard is visible, unless developers specify
window.matchMedia will also be affected in the same manner.
Other clever hacks
There are some other solutions out there for determining browser orientation, including this clever hack that uses CSS Media Queries, but does not rely on
window.matchMedia being supported.
window.orientation is not really all that useful, and
resize event behavior can differ significantly between browsers, we still lack a robust API to report device orientation accurately. For such a basic feature that is commonly needed today, it is pretty ridiculous that a task like this proves to be so overly complicated.