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:
- 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.
- 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.
- 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.
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);totop: anchor(bottom);(with the opposite inset beingauto) will not animate properly - it'll be trying to interpolatetopfromautotoanchor(bottom)(which won't work), and similar forbottom. You can explicitly write atop/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 specifyalign-selftoo:...and
align-selfdoesn't have animation rules to smoothly animate fromstarttoend(yet, #9556). (And even if we did, it wouldn't work quite correctly - analign-self: start 50%;will center in an IMCB with a top of(0% + anchor(bottom))/2and 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:
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 causesautoinsets (andnormalself-alignment) to resolve accordingly. Soinset-area: top anchor(bottom);, for example.autoinsets (andnormalself-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.inset-areadirectly animateable. Addinset-area-mix(...), which represents the interpolated result between twoinset-areavalues. 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 toauto/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.