I am developing a single-page Javascript application that runs on desktop browsers and also on mobile devices via Cordova/Phonegap.
I have a slide-out menu that is implemented using CSS transitions. I noticed that it works well on desktop browsers and android. However, on IOS there are serious performance issues. The transition does not appear to start on time, but once it starts the rendering and duration looks fine. The time between starting the transition and the transitionend event is way higher on IOS than other platforms. For example, the duration of the transition is 300ms but I'm not getting the transitionend event for 1500ms. On all other platforms, I get the transitionend event in 325-350ms.
Transitionend Event:
Platforms:
Here is the CSS for the menu div. To slide-out the menu, I add the 'open' class. To close the menu, I remove the 'open' class. I've tried transitioning on the 'left' property and 'transform' property, but the results are identical.
/* Nav Menu */
#navmenu {
position: absolute;
top: 0;
width: 90%;
max-width: 400px;
z-index: 20;
height: auto;
background-color: white;
/*
-webkit-transform: translate3d(-100%,0,0);
-moz-transform: translate3d(-100%,0,0);
-ms-transform: translate3d(-100%,0,0);
transform: translate3d(-100%,0,0);
-webkit-transition: -webkit-transform 300ms ease;
-moz-transition: -moz-transform 300ms ease;
-ms-transition: -ms-transform 300ms ease;
-o-transition: -o-transform 300ms ease;
transition: transform 300ms ease;
*/
left: -100%;
-webkit-transition: left 300ms ease;
-moz-transition: left 300ms ease;
-ms-transition: left 300ms ease;
-o-transition: left 300ms ease;
transition: left 300ms ease;
}
#navmenu.open {
/*
-webkit-transform: translate3d(0,0,0);
-moz-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
-webkit-transition: -webkit-transform 300ms ease;
-moz-transition: -moz-transform 300ms ease;
-ms-transition: -ms-transform 300ms ease;
-o-transition: -o-transform 300ms ease;
transition: transform 300ms ease;
*/
left: 0;
-webkit-transition: left 300ms ease;
-moz-transition: left 300ms ease;
-ms-transition: left 300ms ease;
-o-transition: left 300ms ease;
transition: left 300ms ease;
}
Question: What might be causing the delay in starting the transition, only on IOS platforms? Are there any known solutions to circumvent the problem or speed things up? I have other transitions in the app that take over 5s to start, making the app unusable. I'm hoping the menu solution will apply throughout the app. Thanks for any help or ideas you can provide.
Here is the instrumented Javascript code that I use to open/close the menu...
utilities.addEventListeners(navMenuButtonDiv, function () {
var start = Date.now();
var menuDiv = navMenu.getDiv();
if (menuDiv.classList.contains('open')) {
menuDiv.classList.remove('open');
} else {
menuDiv.classList.add('open');
}
var handler = function (event) {
console.log('Transition: ' + (Date.now() - start));
menuDiv.removeEventListener('webkitTransitionEnd', handler, true);
};
menuDiv.addEventListener('webkitTransitionEnd', handler, true);
};
When moving elements around the screen, you want to maximize performance. Instead of transitioning the left
property, you're better off using translation. Using translation, the device will use its GPU to render the onscreen change, on a layer above the DOM. This will result in a smoother, more performant transition.
Have a look at this example. Besides using a transform
instead of changing the left
property, notice that I removed a bit of redundancy. You don't need to redeclare the transition on the active state.
var open = document.getElementById("open"),
close = document.getElementById("close"),
nav = document.getElementById("navmenu");
open.addEventListener("click", function() {
nav.classList.add("open");
});
close.addEventListener("click", function() {
nav.classList.remove("open");
});
#navmenu {
position: absolute;
top: 0;
left: 0;
width: 90%;
max-width: 400px;
z-index: 20;
height: auto;
background-color: white;
transform: translate3d(-100%, 0, 0);
-webkit-transition: transform 300ms ease-in-out;
-moz-transition: transform 300ms ease-in-out;
-ms-transition: transform 300ms ease-in-out;
-o-transition: transform 300ms ease-in-out;
transition: transform 300ms ease-in-out;
}
#navmenu.open {
transform: translate3d(0, 0, 0);
}
button {
margin-top: 100px;
}
<div id="navmenu">stuff in here</div>
<button id="open">Open Menu</button>
<button id="close">Close Menu</button>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With