$.animate() runs a timer, writes an inline style on every tick and reads the layout back to work out the next one. The browser is doing the same work either way, but a CSS transition lets it schedule the frames itself and skip the property reads entirely.
/* a timer, a style write and a layout read per tick */
$('.drawer').animate({ left: 0 }, 250);
/* the browser owns the timing */
.drawer {
-webkit-transition: -webkit-transform .25s ease-out;
transition: transform .25s ease-out;
-webkit-transform: translateX(-320px);
transform: translateX(-320px);
}
.drawer.is-open {
-webkit-transform: translateX(0);
transform: translateX(0);
}
The real gain is transform rather than left. Animating left, top or width invalidates layout on every frame whichever side drives it; transform and opacity are the two the compositor can move without touching layout at all, which is where the difference on a phone comes from. Two costs. IE9 has no transitions, so the class change is instant there — a degradation rather than a break, but worth deciding on deliberately. And finding out when it finished means listening for transitionend under three prefixes plus a fallback timer, because the event never fires if the property did not actually change.