Suppose I toggle a class on an element, and this triggers a CSS transition that lasts 2s.
Is there a way to get the computed value of the animated property (or properties) at any point during the animation? If there is more than one way, what is the best way?
I am guessing that I can make a loop with requestAnimationFrame and continually poll for the computed properties, but I haven’t tested this yet, and plus it feels really hacky in general to be polling for things.
Also, and unfortunately, MutationObserver doesn’t have a way to observe an element’s computed styling. That may be a nice feature! The MO callback for such a feature would ideally fire right before the following animation loop. I suppose this isn’t any worse than polling, technically, but it may seem less hacky (though, in practice, maybe both are effectively the same, but one is explicit and fires only if a change actually happened, while the other needs to poll in order to determine if a change happened).
EDIT: I forgot that CSS transitions don’t work with --custom properties. That puts a huge damper on things. Oh wait, the new CSS Properties and Values API Level 1 allows custom properties to be transitionable!
Sure you can use getComputedStyle() to read the animated style. Reading it in a requestAnimationFrame callback will mean you get the values for that frame. (requestPostAnimationFrame would allow you to avoid forcing a synchronous style flush but it probably won’t make much difference in most cases.)
If you want to seek the animation to a particular point you can use getAnimations() to get the transition and then set its currentTime.
Ok, you said “Is there a way to get the computed value of the animated property (or properties) at any point during the animation” which I assumes means you already know an animation is running?
Most animations change their target properties on each frame in their active interval (step timing functions and repeated keyframes being a few of the rare exceptions) so there is little additional overhead from using requestAnimationFrame, assuming the animation is running on the main thread.
If you want to avoid polling when no animation is running you could listen for animationstart/animationend and transitionstart/transitionend events. This would also have the advantage of skipping the delay phase. Unfortunately there is no such event for animations generated using the Web Animations API.
I believe at least Firefox and Chrome internally have an animation mutation observer mechanism that reports when new animations are generated/updated/deleted. This is used for DevTools but, at least in Firefox, it does not notify for changes to animated style.
For the Houdini issue, might I suggest you move the use cases to the top of the issue. Requesting a non-polling API begs the question of why the use cases require that. In fact, you will likely receive more constructive feedback if you focus on the concrete problem rather than the proposed solution.
That’s true! I had figured along those lines, so I suggested in that Houdini issue that the observer can observe only certain specified properties, and that unlike with DOM mutations, it would only observe the final state of animation once the handler is fired (so there would be only one item in the mutation list), which would prevent the engine from having to calculate styles potentially many times before finally triggering the observer callback.
If the only observed property is a --custom property, then in that case the engine can entirely skip reflow/relayout, and just supply the inherited value to the observer callback, because --custom properties, as far as I know, are values only, not computed values (unless they have calc(), but the calc()ed value does not involve a reflow/relayout).
In some cases, we may only want to observe a non-custom CSS property’s pre-computed value (not the computed values). getComputedStyle doesn’t provide this for us. If there was a way to specify that we want pre-coputed values with the MutationObserverInit object (or a CSSPropertyObserverInit for CSSPropetyObserver, or similar (and adding a getPreComputedStyle function too)) then we could have the engine tell us what the pre-computed values are (f.e. height: 100% is always going to give us back 100% for the value, regardless what the actual size is), and therefore we can also avoid reflow/relayout when we know we don’t need it.
As an example, a custom rendering engine could take values from 0% to 100% to determine how to draw WebGL objects, without needing the computed values of the DOM counterparts. The graphics could still be in sync (a DOM element with 100% size as well as a WebGL object with the same size on the screen, but via its own calculations based on percentages and not actual size values).
EDIT: What about ResizeObserver? I imagine, that it must have the same considerations, because in order to tell you the size of an element, it would need to use computed values from reflow/relayout. It seems a CSSPropertyObserver would be similar, when wanting to observe computed values.