Re: Advanced Transitions, Targeting Individual Transition Edges

I spent some more time discussing this proposal internally, and we
found some problems that make it hard to use.  Here's some slight
amendments.

On Fri, Apr 1, 2011 at 3:46 PM, Tab Atkins Jr. <jackalmage@gmail.com> wrote:
> Running an Animation on Arbitrary State Changes
> -----------------------------------------------
(That is, the "state-*" property proposal.)

This is more of a pointer, not a problem.

Most applications/widgets indicate their state in the DOM via either
classes or attributes.  Attributes are great, because they have the
right behavior you want - each attribute defines a state group, and
the values are mutually exclusive (an attribute only has one value at
a time).

Originally, we thought this would be verbose to tie back into the
state-* properties.  For example, we assumed that authors would end up
having to write something like this:

foo[bar='a'] { state-bar: a; }
foo[bar='b'] { state-bar: b; }
foo[bar='c'] { state-bar: c; }
...

This is a ton of duplication, and is annoying.  We realized today in
the discussions that, since transitions fire on changes in the used
value of a property, this can be simplified considerably.  If you're
tagging element with state via the DOM, you can just write a single
rule:

foo { state-bar: attr(bar, keyword, default-value); }

...and you're done - all the "states" you're expressing via values on
the attribute will now be tracked, and can have transitions keyed off
of them.


> Setting Animations on Transition Edges
> --------------------------------------
(That is, the "@transition" rule proposal.)

After trying to actually write some examples using @transition, we
realized that this was *ridiculously* verbose.  You had to duplicate
the selector and property name for every edge, and just generally
write a lot of cruft to accomplish anything decent.

Further, there are some things that you don't really want to put on a
single edge, but rather on the entire transition graph, such as what
to do when a transition is interrupted.

Some discussion led to a solution to both of these problems.  Rather
than describe it, I'll just give an example:

@transition-graph foo {
  over: display;
  interrupt: generate-new;
  @edge(none,block) { animation: ...; }
  @edge(block,none) { animation: ...; }

  /* all edges leading to the "inline" state */
  @edge(*,inline)   { animation: ...; }

  /* Implicitly also define the flexbox=>block edge. */
  @edge(block,flexbox) { animation: ...; reverse: reverse; }
}

(All syntax is very much provisional, obviously.)*

This defines a set of transitions for elements matching the selector
"foo".  You only have to state what property the transition graph is
for *once*, and the edge descriptions are terser while still being
clear.  I can also put properties that should apply to the transition
graph itself directly on the graph, where it belongs.

If there are multiple @transition graph rules that define the same
edges for a particular element, they should cascade in the obvious way
(using the specificity of the selector the graph is defined with).
(Another thing we could do is have them can just collect together, so
that you can have multiple animations firing over the same state
transition.)  Same with special graph properties like 'interrupt' - if
multiple @transition-graph rules define an 'interrupt' rule for the
same property on a particular element, they cascade in the obvious
way.

A further idea that I'm not totally convinced about relates to the
fact that, as I stated earlier, a widget will usually store state in
attributes.  Given that, we can potentially eliminate the rule I
outlined earlier in this email that explicitly maps an attribute's
value into a property's value, and just reference the attribute
directly, like:

@transition-graph foo {
  over: attr(bar);
  @edge("a","b") { ... }
  ...
}

I dunno if it's worth the extra syntax for the benefit of avoiding a
single line per element/attribute.

Thoughts on the original model + the improvements I outlined here?

~TJ


* Special note!  Here's how that example would have looked in the old syntax:

@transition foo {
  over: display;
  from: none;
  to: block;
  animation: ...;
}

@transition foo {
  over: display;
  from: block;
  to: none;
  animation: ...;
}

@transition foo {
  over: display;
  to: inline;
  animation: ...;
}

@transition foo {
  over: display:
  from: block;
  to: flexbox;
  animation: ...;
  reverse: reverse;
}

/* Plus something undefined to specify how to handle transition
interruptions. */

I don't know about you, but I like the new one *way* better.

Received on Friday, 15 April 2011 00:09:16 UTC