⚠️ Warning: this is an old article and may include information that’s out of date. ⚠️
Introduction
If you read part 4 of this series, you’ll know that because of the variety of screen sizes, the best way to develop for mobile is to develop fluid layouts that take 100% of the available space on the screen.
What you probably didn’t think of is that there’s different screen widths even on the same device! This is due to screen orientation. And when the user changes the screen orientation, stuff may break (hey, it’s not a perfect world). In my experience this has meant needing to tweak percentage widths on elements, but I imagine there’s even more needs. Imagine an image carousel that can only fit three images across in portrait mode but can possibly fit four images in landscape mode. It might be nice to re-initialize the carousel to accommodate a forth image when the phone is in landscape mode (then again, that might create a lot of unnecessary overhead…).
In any case, I hope you can agree that it would sometimes be useful to know the screen orientation.
window.orientation
and the orientationchange
event
Luckily on the latest smartphones you have some goodies available to you that you don’t have on the desktop (since desktop users aren’t in the habit of constantly turning their screens sideways!).
-
window.orientation
: this property gives the current screen orientation: 0 in portrait mode, 90 when rotated left, -90 when rotated right (no special value when the screen is upside-down) -
orientationchange
event: this window event fires after every 90 degrees of rotation and, like other events, can be applied in various ways:
|
|
Some websites recommend using orientationchange
to dynamically add an orient
attribute on the body
element and target the orientation with CSS selectors (body[orient=landscape]
), but this is in error. As it turns out, orientationchange
is only fired AFTER the screen has been rotated (which also triggers a CSS reflow), which means this attribute is updated later (after the reflow). And unfortunately editing this orient
attribute doesn’t trigger another CSS reflow. The result? When you rotate the device, these new CSS styles don’t get applied!
The fix is to add the orientation as a CSS class, which does trigger a CSS reflow. So our code at this point will look something like this:
|
|
Now we can target elements like this in CSS:
|
|
With a little help from media queries
You may have heard of media queries being used to target mobile devices (based on screen pixel width) or to target the iPhone 4’s Retina display, but you may not have known that you can also target screen orientation!
|
|
The orientation media query is available on iOS 3.2+, Android 2.0+, and some other browsers.
This is a lot cleaner than the above JavaScript example in the sense that it’s pure CSS, and it’s part of the CSS that gets reflowed when the screen is rotated.
(Minor note: iOS 4 on the iPhone Simulator running 4.0.0 looks like it’s stuck in landscape orientation, but the media queries work correctly on my 3GS with 4.0.1)
Fallback: when window.orientation and media queries aren’t available…
If window.orientation
isn’t available on a device, chances are the orientationchange
event and media queries (for orientation) will also not be available. Oh no, what do we do now?
Even though this isn’t an entirely foolproof method, we can dynamically measure the window width and height and guess orientation based on that:
|
|
Ok, so it’s not pretty, but it seems to work. The overhead in this fallback example is the fact that we have to use a polling technique (in this case every 5 seconds [5000 milliseconds]) to check for changes in orientation.
Note: there’s also the strong possibility that these browsers will not support the DOMContentLoaded
event, but we’ll ignore that for the purposes of this article. (if you have problems, change DOMContentLoaded
to load
).
Putting it all together
Ok, so if you want the fallback example to work in addition to newer methods, unless you want to duplicate your CSS, then avoid using media queries to target orientation. Instead we’ll rely on adding a class to the html
tag (or the body
tag if you prefer).
Once we put everything together, we get something that looks like this:
|
|
Minified (540 bytes):
|
|
Conclusion
And that’s it! Now we can reliably target different screen orientations with some straightforward CSS:
|
|
Again, in my experience I’ve used this to fix bugs. But I’m sure you can find more creative uses for it!
Related
iPad web development tips (Nicholas C. Zakas)
iPhone window.onorientationchange Code (Ajaxian)
The orientation media query (Quirksmode)
Comments