Skip to content

[css-anchor-position][css-position] Fixing the animation problem #9598

Closed
@tabatkins

Description

@tabatkins

Edit: This comment's proposal is out of data, our current proposal is over here.

Issue: Because the inset properties are four separate properties, you can't animate them "together" - instead you can animate each of the four independently, and hope that what you're expressing is reasonable for that to work. That's not always true!

For example, going from bottom: anchor(top); to top: anchor(bottom); (with the opposite inset being auto) will not animate properly - it'll be trying to interpolate top from auto to anchor(bottom) (which won't work), and similar for bottom. You can explicitly write a top/bottom: 0; in each case, which will technically animate, but not in a useful way; now, to get things to line up correctly, you'll need to specify align-self too:

.first {
  top: 0;
  bottom: anchor(top);
  align-self: end;
}
.second {
  top: anchor(bottom);
  bottom: 0;
  align-self: start;
}

...and align-self doesn't have animation rules to smoothly animate from start to end (yet, #9556). (And even if we did, it wouldn't work quite correctly - an align-self: start 50%; will center in an IMCB with a top of (0% + anchor(bottom))/2 and a bottom of (0% + anchor(top))/2, and that is very likely not halfway between its starting and ending position. In general, this sort of "interpolate a position within an interpolating range" doesn't produce a linear interpolation of the position in an absolute context; it produces a quadratic spline path instead.)


So that's the issue. How do we solve it? Here's my suggestion:

  1. Repurpose inset-area. In addition to the existing grid-based syntax, add a [ <side-keyword> <length-percentage> ]{1,4} production, which similarly defines a rectangle and causes auto insets (and normal self-alignment) to resolve accordingly. So inset-area: top anchor(bottom);, for example.
  2. Change the inset-area rules so that, rather than resolving auto insets (and normal self-alignments) at computed-value time, they resolve at used-value time. This removes the ability to animate the inset properties directly from the inset-area value.
  3. Instead, make inset-area directly animateable. Add inset-area-mix(...), which represents the interpolated result between two inset-area values. This represents whatever insets and alignments would be required to make the position of the element interpolate smoothly between the two endpoints (rather than being a naive interpolation of edges and alignment). So long as all your actual inset properties and self-alignment properties are set to auto/normal, it'll Just Work.

I still need to give a little more thought to how the new side-based production handles alignment. In the grid syntax I can pretend that the default anchor is inside the containing block, so all the grid lines are correctly ordered and I can infer some positioning, but that's more difficult when the edges can indeed be misordered due to positioning. I'm pretty sure there's a good solution here, I just haven't fully worked thru it yet.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Tuesday morning

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions