Note that there are some explanatory texts on larger screens.

plurals
  1. POjavascript max viewport height after orientation change Android & iOS
    text
    copied!<h2>The Goal:</h2> <p>To find the max viewport height of a device including the space of the <code>address bar</code> so that we can dynamically resize the min-body and push our content up.</p> <h2>The Problem:</h2> <p>Mobile browsers handle orientation states differently and update DOM properties on orientation change differently.</p> <p><a href="https://stackoverflow.com/questions/1649086/detect-rotation-of-android-phone-in-the-browser-with-javascript">Detect rotation of Android phone in the browser with JavaScript</a></p> <p>With Android phones, <code>screen.width</code> or <code>screen.height</code> also updates as the device is rotated.</p> <pre><code>|==============================================================================| | Device | Events Fired | orientation | innerWidth | screen.width | |==============================================================================| | iPad 2 | resize | 0 | 1024 | 768 | | (to landscape) | orientationchange | 90 | 1024 | 768 | |----------------+-------------------+-------------+------------+--------------| | iPad 2 | resize | 90 | 768 | 768 | | (to portrait) | orientationchange | 0 | 768 | 768 | |----------------+-------------------+-------------+------------+--------------| | iPhone 4 | resize | 0 | 480 | 320 | | (to landscape) | orientationchange | 90 | 480 | 320 | |----------------+-------------------+-------------+------------+--------------| | iPhone 4 | resize | 90 | 320 | 320 | | (to portrait) | orientationchange | 0 | 320 | 320 | |----------------+-------------------+-------------+------------+--------------| | Droid phone | orientationchange | 90 | 320 | 320 | | (to landscape) | resize | 90 | 569 | 569 | |----------------+-------------------+-------------+------------+--------------| | Droid phone | orientationchange | 0 | 569 | 569 | | (to portrait) | resize | 0 | 320 | 320 | </code></pre> <p>Because of this it is clear that to find the max viewport height no matter what orientation, using a single function to return the max height of a device will never be constant over a range of devices.</p> <p><strong>Other problems I have discovered that don't make these two play nice:</strong></p> <ul> <li>The <code>window.devicePixelRatio</code> property can return inconsistent heights when dividing by <code>window.outerHeight</code>.</li> <li>Delay <code>window.setTimeout(function() {}, time)</code> needs to be used to give DOM elements a chance to update after orientation change.</li> <li><code>window.outerHeight</code> is not updated on orientation changes for iOS devices. Using <code>screen.availHeight</code> as a fallback includes the bottom nav bar as total height.</li> <li>Using a <code>#header</code>, <code>#content</code>, <code>#footer</code> structure forces you to dynamically recalculate the <code>#content{min-height}</code> to push the <code>#footer</code> down when the <code>body</code> is dyamically updated.</li> </ul> <h2>A Solution:</h2> <p><strong>First let's take a look at DIV structure:</strong></p> <pre><code>&lt;style&gt; #header,#content,#footer{width:100%;} &lt;/style&gt; &lt;body&gt; &lt;div id="header"&gt;&lt;/div&gt; &lt;div id="content"&gt;&lt;/div&gt; &lt;div id="footer"&gt;&lt;/div&gt; &lt;/body&gt; </code></pre> <p><strong>We want to prevent devices from scaling on their own:</strong></p> <pre><code>&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" /&gt; </code></pre> <p><strong>We need help to have the ability to return a max viewport height and hide address bar for iOS:</strong></p> <pre><code>&lt;script src="iOS.js" type="text/javascript"&gt;&lt;/script&gt; </code></pre> <p><a href="http://iosjs.com/" rel="nofollow noreferrer">http://iosjs.com/</a></p> <p><strong>Then detect if the device supports orientation change and use resize as a fallback:</strong></p> <pre><code>var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/i) ? true : false); var android = (navigator.userAgent.match(/Android/i) ? true : false); var supportsOrientationChange = "onorientationchange" in window; var orientationEvent = supportsOrientationChange ? "orientationchange" : "resize"; </code></pre> <p><strong>The belly of the beast:</strong> </p> <pre><code>function updateOrientation() { var orientation = (window.orientation); if(android) { window.setTimeout(function() { window.scrollTo(0,0); var size = window.outerHeight/window.devicePixelRatio; $('body').css('min-height', size + 'px'); var headerHeight = $('#header').height(); var footerHeight = $('#footer').height(); var contentHeight = size - (headerHeight+footerHeight); $('#content').css('min-height', contentHeight + 'px'); window.scrollTo(0,1); }, 200); } if(iOS) { window.setTimeout(function(){ window.scrollTo(0,0); var size = iOS_getViewportSize(); var headerHeight = $('#header').height(); var footerHeight = $('#footer').height(); var contentHeight = size.height - (headerHeight+footerHeight); $('#content').css('min-height', contentHeight + 'px'); window.scrollTo(0,1); }, 0); } } </code></pre> <p><strong>Add event listeners for page load and orientation event:</strong></p> <pre><code>if(iOS) { iOS_addEventListener(window, "load", iOS_handleWindowLoad); iOS_addEventListener(window, "orientationchange", iOS_handleOrientationChange); iOS_addEventListener(window, "resize", iOS_handleReize); } addEventListener("load", function() { updateOrientation(); }, false); addEventListener(orientationEvent, function() { updateOrientation(); }, false); </code></pre> <h2>Proof is in the pudding:</h2> <p><strong>iPhone 4 &amp; 4s Portrait &amp; Landscape</strong></p> <p><img src="https://i.stack.imgur.com/IiE8m.png" alt="iPhone 4 &amp; 4s Portrait"> <img src="https://i.stack.imgur.com/VqeGG.png" alt="iPhone 4 &amp; 4s Landscape"></p> <hr> <p><strong>Android Portrait &amp; Landscape</strong></p> <p><img src="https://i.stack.imgur.com/3LdRh.jpg" alt="Android Portrait"> <img src="https://i.stack.imgur.com/kJNQ3.jpg" alt="Android Landscape"></p> <hr> <h2>The goal here is to minify this solution or make it better.</h2>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload