3
\$\begingroup\$

One hassle with working with mobile websites is inconsistency between how the device reports the screen's width and height. James Pearce wrote a fantastic article about the headaches that come with detecting screen width and height from JavaScript. Furthermore, not all mobile devices support window.onOrientationChange and window.orientation members (and those that do don't necessarily do so consistently either).

Because of this, I'm working on a snippet to detect orientation and polyfill if it's not supported. The issue that I have, though, is dealing with identifying when the orientation changes on multiple devices.

The below snippet works on small screens (e.g. Android and iPhones):

var newOrientation
, currentWidth = document.getElementsByTagName("body")[0].clientWidth;
// since there's bugs around devices supporting and reporting screen.width, using body instead

// set orientation
// TODO: Correct hard coded breakpoint.
if (window.hasOwnProperty("orientation")) { newOrientation = window.orientation; }
if (typeof newOrientation === "undefined") { newOrientation = (currentWidth > 400) ? 1 : 0; }
  1. The code declares the newOrientation to test for the change against the currentOrientation variable (not shown).

  2. Because of issue with screen.width, I'm grabbing the body tag's clientWidth property as a benchmark (CSS has body.width set to 100%)

  3. Next, I set newOrientation to window.orientation if the browser supports such.

  4. Finally, I check if newOrientation has been defined yet and if not, change it if the width is over a certain breakpoint (in this case, 400 which covers most phones).

I'm trying to find a better way to do point 4 since it doesn't scale well if I apply it to a Kindle Fire (600x1024) or an iPad2 (768x1024). One thing preventing me from comparing height to width is how long pages would skew this logic.

Does anyone have any suggestions how I might be able to modify this to compensate for larger screen widths?

Update After reviewing the linked article more and also taking into consideration GGG's suggestions, the code was refactored to the following:

var newWidth = window.outerWidth
  , newOrientation = window.orientation || (newWidth !== currentWidth) ? 1 : 0;

if (newOrientation !== currentOrientation) {
    currentOrientation = newOrientation;
    currentWidth = newWidth;
}
\$\endgroup\$
1
\$\begingroup\$

First, the code above can be simplified a lot, at least for the purposes of this "review," and rewritten as:

var currentWidth = document.body.clientWidth,
    newOrientation = window.orientation || (currentWidth > 400);

Second, I'd probably be really sure I'm getting a good width value by doing something like this:

var currentWidth = window.innerWidth || document.body.offsetWidth || document.documentElement.offsetWidth,
    newOrientation = window.orientation || (currentWidth > 400);

Next, none of these devices are perfectly square, right, so instead of checking against a constant, why not check if it's wider than it is tall?

var currentWidth = window.innerWidth || document.body.offsetWidth || document.documentElement.offsetWidth,
    currentHeight = window.innerHeight || document.body.offsetHeight || document.documentElement.offsetHeight,
    newOrientation = window.orientation || (currentWidth > currentHeight);

If I understand your question correctly, this should fix the problem with the larger screens.

Also note that this approach will only work reliably if the viewport is the same size as the physical screen. As you probably know, this can be accomplished with the viewport meta tag:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

If you're not setting a viewport, you'll get weird behavior. For example, some mobile browsers seem to keep the viewport settings from the last loaded site when a site with no viewport meta tag loads.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the first suggestion since it is a refactor I can definitely implement. Also, I am constraining the viewport of the page and use the html 5 doctype. These are two things I neglected to mention. Sadly though, window.innerWidth, document.body.offsetWidth, and document.documentElement.offsetWidth (and their corresponding Height properties) are too inconsistent across devices and platforms to use based on research in the link provided in the post. I will definitely look for an alternative height comparisons though. Thanks \$\endgroup\$ – JamesEggers Feb 28 '12 at 23:02
  • \$\begingroup\$ @JamesEggers maybe i'm reading this article wrong, but as far as I can tell this should give you close enough values to at least tell whether the screen is taller than it is wide, which is as much accuracy as it seems like you need. Am I missing something? \$\endgroup\$ – Dagg Feb 29 '12 at 5:19
  • \$\begingroup\$ After reviewing the article again again and considering your feedback, you are correct. However, diving a bit deeper, it would appear that I won't need to test width vs height since window.outerWidth using Html5 doctype and with the viewport constrained appears to work across the board if window.orientation doesn't exist. I'll update the original post to reflect such. Thanks for your assistance on this. \$\endgroup\$ – JamesEggers Feb 29 '12 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.