Re: [css-grid] Are grid positions animatable?

On Thu, Nov 14, 2013 at 5:45 PM, Jon Rimmer <jon.rimmer@gmail.com> wrote:
> Hi all,
>
> Apologies if this has been asked before, but I'm wondering if the position
> of items in a grid layout are intended to be animatable? The properties in
> the spec do not specify one way or the other.
>
> I ask because I contend that the ability to animate elements from one layout
> position to another is an important use case, and one where the web
> struggles to match the UI experiences provided by native apps. Right now the
> only way to do this is through JS layout libraries [1] and impressive hacks
> like Steve Sanderson's use of generated nth-child specific transforms [2].
> If grid positions were able to be transitioned, particularly for
> automatically placed items, it would make it very easy to build lists and
> grids that responded nicely to insertions, removals, reorderings, etc.

As Daniel said, yes, they're probably interpolable (though we haven't
defined that, and you can't just assume since the value space is
non-trivial), but that won't help you as it wont' do the smooth
flying-around that you want.

The fundamental issue is that CSS Transitions and Animations all act
on property values, and property values only.  They work well when the
thing you're animating has intermediate states that can be expressed
with CSS properties as a linear combination of the start and end
values, but are completely worthless outside of that.  There is no way
to use Grid to write that something is halfway between cell A and cell
B, so you can't do what you're asking for with T/A.

I've been working on this problem for a while internally in Blink.  We
came up with a declarative solution to this, but it was a bit
heavyweight and didn't actually work for a lot of reasonable cases, so
we scrapped it.  Instead, we're first focusing on a basic JS API to
make this easier to do manually.

Basically, current approaches revolve around either doing all layout
in JS (which is then easy to animate), or doing complicated things to
measure the position/size at the endpoint (usually involving cloning
an element into an off-screen container and duplicating styles as well
as you can) and then animating it in JS.

Our approach is to make this easier to do:

1. Have an API to completely turn off painting for an element.
Turning off painting is identical to setting "visibility:hidden",
except children can't opt out; it's a separate API to keep from
screwing with the page's styles.  The element still takes up
space/etc.

2. Have an API to take "snapshots" of an element, regardless of
whether its painting is turned on or off.  (If it's off, it paints for
the snapshot, but not for the screen.)  This function call returns an
opaque object that can't be directly inspected, but *can* be assigned
to the element() map
<http://dev.w3.org/csswg/css-images/#elementsources> and used as a CSS
image.

This is all you need.  Doing fancy grid animations is still some work
in JS, but all the hard/hacky stuff has been taken out.  You just:

1. Turn off painting for the grid container.
2. Snapshot all the grid children, and insert dummy <div>s using the
snapshots as background-images over the top of each of the elements.
(Measuring and positioning should be relatively easy with the new
Geometry APIs <http://dev.w3.org/FXTF/geometry/>.)
3. Switch the style to the end-state.
4. Snapshot all the children again, and measure any relevant
size/positions you need.
5. Do the animation you want on the dummy <div>s - cross-fade() the
images or whatever, animate the positions, etc.
6. When finished, turn painting back on and delete all the dummy <div>s.

Done.  It's still something that you'll want a library to do for you,
but it's much more performant and reliable than the existing methods.

Received on Friday, 15 November 2013 23:16:30 UTC