ACTA: Analysis of Missing Features

From Effects Task Force

(please see Advanced CSS Transitions & Animations Proposal for the proposal that this analysis discusses)

Introduction

Recently, Google has provided a proposal for advanced CSS Transitions & Animations, which provides a great deal of declarative control over animations, to the extent of allowing the specification of complex declarative widget behaviors.

This document addresses two questions:

  1. can the behaviors suggested by this proposal easily be replicated with existing web technologies?
  2. if not, what's missing that would allow them to be?

Emulation of Proposal in JavaScript

I have successfully emulated most of the proposal in JavaScript (the source code is in the process of being released and will be available soon), however it wasn't possible to do this in an efficient manner. The emulation is broken up into four parts:

  1. excss, which includes an in-browser CSS parser and rewrite mechanism.
  2. a parser/rewrite extension to excss that handles the grammar suggested in the proposal.
  3. a css event emulation library (to be released), which:
    1. determines when CSS changes have occurred and packages these changes up as events provided to callbacks; and
    2. allows the definition, setting, and tracking of novel properties that do not exist in CSS.
  4. a library that implements the behaviors suggested by the proposal.

Of these four components, the first two relate solely to interpreting a CSS-specific encoding of the animation state machines, and can therefore be safely ignored in this discussion.

Supporting the proposal

The third component detects changes in CSS state, where state can be:

  1. changes in the computed style applied to an element
  2. changes in the set of style rules that apply to an element
  3. changes in the values of properties set within a given style rule

In order to support the proposal as currently drafted, these changes need to be tracked - for example, if the computed style of an animated element changes, then that change might include a change in a state- property, which would trigger a state change.

Removing the specifics of the proposal and looking more generally, it's desirable to be able to trigger animations off UA events like changes in hover status - in fact, both transitions and animations in CSS are very heavily used in this manner. Unfortunately, detecting changes like this from JavaScript is very slow and quite difficult - effectively all DOM change events as well as mouseover/mouseout and mousedown/mouseup events need to be intercepted and inspected.

Solving this problem in some reasonably efficient manner within the web platform is basically essential to implementing this proposal efficiently in JavaScript.

The mechanisms of the proposal

The final component consists of just over 1000 lines of JavaScript, and implements the following behaviors:

  • per-animation state graph storage - this is reasonably complicated as animations are defined piecemeal and need to be assembled based on the relative specificity of the selectors associated with each piece.
  • per-animated-element instantaneous and animated state tracking - this is quite straightforward. Changes to state are triggered at this level by callbacks from the CSS event emulation library.
  • @-webkit-keyframes declaration generation (for emulation of proposed from() and to() functions) - this is pretty simple
  • shortest path calculation for state graphs - this isn't precisely simple, but follows a well-known algorithm (Dijkstra's algorithm for shortest paths)
  • conversion of shorthand to longhand for CSS properties - this is only partially implemented, and is needed because of WebKit's computedStyle behaviour (it provides only longhand values, which means that animations specified as shorthand need to be converted to longhand before from() and to() functions can be correctly emulated).

This isn't a small library, but much of it could be removed if:

  • relative keyframes (from(), to() and prev() functions) were implemented by the web platform - this would remove both the declaration generation code and the need to convert shorthand to longhand.
  • the CSS declarative syntax were abandoned and state machines were only generated procedurally - this would remove the need to build up state machines from rules associated with selectors of various specificities.

The result would be a library that tracked state machine structures and per-element state, and that applied pre-existing keyframes definitions to elements based on the differences between current animated state and instantaneous state for each of these elements. Instantaneous state changes would be generated by function calls, which would need to be manually hooked up to event callbacks.

In order to fully match the proposal, support for animation blending also needs to be implemented, however again this could be provided by the web platform as it's a generally useful feature.

Conclusions

With the following features baked into the web platform:

  • some form of CSS events mechanism
  • relative keyframes (from(), to(), prev() functions)
  • animation blending

much of the rest of the proposal would fall out reasonably easily and efficiently in JavaScript