CSS Transitions & Animations
The best opportunity for smooth animations are CSS transition and keyframe animation based, especially tapping into hardware-accelerated transforms and opacity changes. Below are notes that summarise a number of very useful articles. Any credit belongs to those.
Letting the browser control animation sequences allows it to optimise performance and efficiency by altering the frame rate, minimising paints and offloading some of the work to the GPU.
Duration is the only required item in the shorthand declaration of CSS transitions. The timing function defaults to "ease" and the property defaults to "all". Browsers have a set of built-in timing functions, such as linear, ease, ease-in, ease-out, ease-in-out. However, for more complex timing functions we can define our own by specifying four points along a cubic bezier curve (http://cubic-bezier.com/ & http://easings.net/).
It's worth noting that not every css property can be transitioned. There is a finite list (http://oli.jp/2010/css-animatable-properties/). A basic rule is that you can only transition a property through absolute values.
It's worth noting that the transitionend event will bubble up from any child selector that also has a transition, resulting in more events being fired than would be expected. To stop the event from bubbling we can stop the event from propagating each time we bind it. e.stopPropagation();
CSS animations are based on keyframes - a start or end point in an animation sequence. The time between these frames is known as the 'tween' or in CSS, the transition. We can define as many frames during this transition period as required, allowing complex animation sequences to be created. In contrast, with transitions we have little control beyond the end result.
At this time, animations are still an experimental feature and therefore require vendor prefixes for maximum coverage. http://caniuse.com/#feat=css-animation. In cases where proper function of a site is reliant on animations and/or transitions, it's important to consider fallback methods in order to expose the same end result.
For a detailed overview of CSS animation syntax, visit dev.opera.com/articles/view/css3-animations. Of particular interest is the lesser known animation-fill-mode property which allows us to specify how an element is displayed after an animation ends, or during an animation-delay. We can use this property to retain styles defined during an animation even after the animation ends.
Performance & Hardware Acceleration
Whilst most CSS transitions/animations across various properties will give good results, modern browsers can animate 4 particular properties really easily - position/translation, scale, rotate (i.e. transformations) and opacity. Animating anything else risks less than optimal animation frame rates in comparison. The reason for this is the animation rendering can be offloaded to the GPU when using CSS transformations. Simply, this means that elements are turned into images during the transition/animation, avoiding style recalculations and improving performance significantly.
This method of "hardware acceleration" can be triggered by setting the transformations z axis, which can be done with translate3D. This isn't a silver bullet and comes with its own considerations though. It shouldn't be enabled on every element, only when required. Hardware acceleration can sometimes cause subtle font issues. The short-term (controversial) fix is to disable sub pixel anti-aliasing completely. However, do your research before doing this as there are important considerations. If there is flickering or juddering with hardware acceleration, check elements aren't being nested with the transform3D property set.
The translate3D hack is becoming less relevant as browsers move towards automatically using the GPU for transitions. Also of note is that ios6 has explicitly disabled the translate3D trick and requires workarounds (http://indiegamr.com/ios6-html-hardware-acceleration-changes-and-how-to-fix-them/).
Animation Performance in More Detail
The process a browser follows when animating is: calculate styles that apply to the element (recalc styles), generate the geometry and position of all affected elements (layout), fill the pixels for each element into layers (paint) and draw the layers out to screen (composite layers).
Transitioning certain properties such as left, margin, width etc causes the browser to recalculate styles and affects layout at every frame. This is expensive and can lead to unnecessary repaints. The larger the DOM tree the longer it takes to perform these layout calculations, as changes may impact lots of child elements also. This will have the most notable impact on performance in less powerful devices such as mobile devices.
By changing only properties that affect compositing in our animations and avoid tiggering layout changes - transforms and opacity, we stand the best chance of achieveing smooth animations, especially when tapping into hardware acceleration.
CSS Transitions or CSS Animations
Whilst with transitions a state change is required in order to trigger the animation (e.g. :hover), animations don't require explicit state changes in this way, and can start playing automatically. Another difference is that a transition occurs on properties that change their values, whereas animations can animate between property values even if those properties were not set set in the default state of the elements.
Using the animation-iteration-count property, it's straightforward to loop animations, whereas transitions only run once when triggered. Whilst we could in theory loop transitions by listening for the transitionend event, this adds a level of complexity.
It makes sense that for animations which include multiple frames and/or looping, use of the CSS animation property is likely the favoured approach. That said, the decision process between use of animations and/or transitions is blurry, and as usual depends on a number of different factors.