W3C home > Mailing lists > Public > public-css-archive@w3.org > July 2021

Re: [csswg-drafts] [css-variables] When does substitution occur, before or after animation interopolation? (#411)

From: Tab Atkins Jr. via GitHub <sysbot+gh@w3.org>
Date: Fri, 30 Jul 2021 18:38:31 +0000
To: public-css-archive@w3.org
Message-ID: <issue_comment.created-890081098-1627670310-sysbot+gh@w3.org>
tldr: As far as I can tell, browsers are currently treated variables in animations differently than other computed-value dependencies, and they should stop. The correct behavior was resolved [back in 2014](https://drafts.csswg.org/css-animations/#wg-resolutions-pending), but hasn't been put into the Animations spec. Once it is editted in, variables behavior should naturally fall out, and we don't need any special text for this spec.

----

When figuring out how custom properties work with animations,
there are (at least?) four relevant contexts we need to worry about:

```
.foo { 
	/* A */ 
	animation: test infinite 1s, test2 infinite 1s;
}
@keyframes test {
	from { /* B */ }
	to { /* C */ }
}
@keyframes test2 {
	from { /* D */ }
}
```

That is:
* (a) styles applied directly to an element
* (b) styles appearing in a keyframe
* (c) styles appearing in a *different* keyframe in the same @keyframes
* (d) styles appearing ina  different @keyframes entirely

So there's a 4x4 matrix (with many cells being dupes) 
of locations where a custom property can occur,
and where a var() can show up referring to the custom property,
and we need to figure out in which situations there is data flow.
For example, if a custom property is defined directly on an element (a),
is it visible to var()s in a keyframe (b)?
What about vice versa?

Tests for each situation (named for custom prop location and var() location, like `a/b` for the example above):

Chrome ✔✘, Firefox ✔✘

* a/a: normal animations behavior, not tested
* [a/b, a/c, a/d](http://software.hixie.ch/utilities/js/live-dom-viewer/saved/9523): Chrome ✔, Firefox ✔
* [b/a, c/a, d/a](http://software.hixie.ch/utilities/js/live-dom-viewer/saved/9524): Chrome ✔, Firefox ✘
* [b/b, c/c, d/d](http://software.hixie.ch/utilities/js/live-dom-viewer/saved/9525): Chrome ✔, Firefox ✔
* [b/c, c/b](http://software.hixie.ch/utilities/js/live-dom-viewer/saved/9526): Chrome ✘, Firefox ✘

	Behavior is still slightly different here,
	seemingly due to different timing of the "try to resolve the var() reference" action.
	It looks like Chrome resolves the animation first *then* resolves var()s,
	so the color/bg is just a constant var() ref,
	and the custom prop they're referring to is discretely animating between valid and invalid.
	Firefox instead resolves the var()s before resolving the animation,
	so the color/bg smoothly animates from a color (based on the custom prop) to a color (initial value due to invalid custom prop).

	This is maybe more obvious in <http://software.hixie.ch/utilities/js/live-dom-viewer/saved/9529>,
	where Chrome flashes between two states
	while Firefox smoothly animates between the two states.

* [b/d, d/b, c/d, d/c](http://software.hixie.ch/utilities/js/live-dom-viewer/saved/9527): Chrome ✔, Firefox ✘

	Just in case animation order matters, I tested both "custom prop in animation preceding the var() animation" and vice-versa;
	results were same for both.

Firefox's overall rule seems to be that custom props defined on the element are visible to animations,
and custom props defined in a keyframe are visible *to that keyframe only*
(overriding any custom props coming from the element itself, per usual for animation-origin declarations),
but there is no other data flow.
Chrome's is more complicated.

I *think* both can be explained in the same way, with a single change in var() substitution timing:
both browsers treat custom properties the same as normal properties 
wrt animation styles and element styles mixing,
but Firefox substitutes var()s ASAP
(on elements, before cascading animations;
within animation styles, before interpolation),
while Chrome substitutes var()s as late as possible
(on elements, var()s don't resolve until after animations are cascaded;
within animation styles, var()s stay unresolved until *after* interpolation).

Reviewing some old animation issues
and doing some tests of other computed-value dependencies between animations,
afaict *both* browsers are giving variables different behavior than things like `em` units,
and both are violating the WG agreement to [use option G.β](https://drafts.csswg.org/css-animations/#wg-resolutions-pending)
to resolve computed-value dependencies in the presence of animations.

In particular:

* Firefox's timing wrt resolving var()s in static styles before animations are applied
	means that you can't take a custom property on an element
	and animate it.
	(Contrary to the current behavior where an `em` in static styles
	*is* affected by an animated `font-size`.)

* Chrome's timing wrt resolvings var()s in animated styles *after* interpolation
	means you can't extract common values from properties
	and then animate the properties smoothly.

----

So I think the behavior is actually just something that should fall out of the Animations spec
once someone (sigh, probably me) edits in the G.β option properly.

I initially thought it might still require some special text,
since animation properties could depend on variables 
and thus need an early compute pass over the custom props
(which later gets overridden once animations are applied),
but that's actually true of general properties now,
since the animation properties might depend on font-size
if you, say, specify animation-duration using `em` and unit algebra
to get the units to land on `<time>` in the end.

The general behavior will likely be, then,
that animation properties get computed in an initial pass,
along with a *theoretical* computing of any properties
they happen to grab a dependency to
(custom props, font-size, etc).
Then you set up animations
and re-resolve dependencies as specified by G.β,
potentially getting different values than originally computed.

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/411#issuecomment-890081098 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Friday, 30 July 2021 18:38:33 UTC

This archive was generated by hypermail 2.4.0 : Tuesday, 5 July 2022 06:42:40 UTC