Mobile viewport height after orientation change
Use the resize event
The resize event will include the appropriate width and height after an orientationchange, but you do not want to listen for all resize events. Therefore, we add a one-off resize event listener after an orientation change:
Javascript:
window.addEventListener('orientationchange', function() { // After orientationchange, add a one-time resize event var afterOrientationChange = function() { // YOUR POST-ORIENTATION CODE HERE // Remove the resize event listener after it has executed window.removeEventListener('resize', afterOrientationChange); }; window.addEventListener('resize', afterOrientationChange);});
jQuery:
$(window).on('orientationchange', function() { // After orientationchange, add a one-time resize event $(window).one('resize', function() { // YOUR POST-ORIENTATION CODE HERE });});
Do NOT use timeouts
Timeouts are unreliable - some devices will fail to capture their orientation change within your hard-coded timeouts; this can be for unforeseen reasons, or because the device is slow. Fast devices will inversely have an unnecessary delay in the code.
Gajus' and burtelli's solutions are robust but the overhead is high. Here is a slim version that's reasonably fast in 2017, using requestAnimationFrame
:
// Wait until innerheight changes, for max 120 framesfunction orientationChanged() { const timeout = 120; return new window.Promise(function(resolve) { const go = (i, height0) => { window.innerHeight != height0 || i >= timeout ? resolve() : window.requestAnimationFrame(() => go(i + 1, height0)); }; go(0, window.innerHeight); });}
Use it like this:
window.addEventListener('orientationchange', function () { orientationChanged().then(function() { // Profit });});
There is no way to capture the end of the orientation change event because handling of the orientation change varies from browser to browser. Drawing a balance between the most reliable and the fastest way to detect the end of orientation change requires racing interval and timeout.
A listener is attached to the orientationchange
. Invoking the listener starts an interval. The interval is tracking the state of window.innerWidth
and window.innerHeight
. The orientationchangeend
event is fired when noChangeCountToEnd
number of consequent iterations do not detect a value mutation or after noEndTimeout
milliseconds, whichever happens first.
var noChangeCountToEnd = 100, noEndTimeout = 1000;window .addEventListener('orientationchange', function () { var interval, timeout, end, lastInnerWidth, lastInnerHeight, noChangeCount; end = function () { clearInterval(interval); clearTimeout(timeout); interval = null; timeout = null; // "orientationchangeend" }; interval = setInterval(function () { if (global.innerWidth === lastInnerWidth && global.innerHeight === lastInnerHeight) { noChangeCount++; if (noChangeCount === noChangeCountToEnd) { // The interval resolved the issue first. end(); } } else { lastInnerWidth = global.innerWidth; lastInnerHeight = global.innerHeight; noChangeCount = 0; } }); timeout = setTimeout(function () { // The timeout happened first. end(); }, noEndTimeout); });
I am maintaining an implementation of orientationchangeend
that extends upon the above described logic.