w3c/css-houdini-drafts

[css-properties-values-api] Registering properties in JS could have performance impact

Opened this issue · 4 comments

smfr commented

https://drafts.css-houdini.org/css-properties-values-api-1/
Registering custom properties with the JS API will force the UA to recompute style so that the newly registered properties are applied. However, there's not obvious "right" time to do this, and if the JS runs after the stylesheets have loaded, register properties will trigger potentially--expensive style recomputation.

This also adds another way to trigger expensive "forced style recalc" loops if an author registers multiple properties, asking for computed style after each registration.

For this reason the declarative approach seems preferable to using the JS API.

Wholeheartedly agree. Will Safari be the first to ship the declarative api? 🥺

The Houdini Task Force just discussed perf concerns of custom properties.

The full IRC log of that discussion <TabAtkins> Topic: perf concerns of custom properties
<TabAtkins> github: https://github.com//issues/940
<iank_> smfr: One if the issues w/ this being a JS api, is that there isn't a good time to register the properties.
<iank_> smfr: e.g. stylesheet loads, prop registered, need to recalc stylesheet potentially.
<iank_> smfr: Similar to style recalc thrashing.
<iank_> smfr: Has been a proposal for a declarative version of registered custom properties.
<heycam> q+
<iank_> TabAtkins: It seems like you have the same issues, e.g. if the properties come later in a sheet, or a later style sheet.
<heycam> q-
<iank_> smfr: B/c you only have to parse the properties once. And it'll come in a "batch."
<iank_> dino: You could imagine a bunch of component libs, which each register a custom properties.
<iank_> dino: If delcarative, they come all at once.
<iank_> TabAtkins: How is this different to JS setting this to something different each time?
<iank_> TabAtkins: You need to rerun all the style on the root.
<iank_> smfr: It depends how much work you need to do if the type changes.
<iank_> TabAtkins: If you have an untyped its still the same.
<iank_> TabAtkins: If its still the same, is there much of a concern still?
<iank_> smfr: We should try not to add new APIs let authors pull trigger for a performance cliff.
<iank_> TabAtkins: Would we get everything from the declarative appraoch, yes at the moment, but future levels, e.g. hooks, then no.
<iank_> smfr: Can we just to declar version atm?
<iank_> TabAtkins: As they are equiv. in power. But would be in favour if rewriting the spec to make the declarative version much more promiment.
<iank_> dino: In the spec if it calls out - most optimal way to declare all of them at top, then use them. And explain in the spec to do this.
<iank_> smfr: Also call out how to correctly use the JS api.
<iank_> majidvp: In JS api, you only need to do this if you trigger style reclac.
<iank_> emilio: Did agree that JS -reg properties, @Property do not conflict. JS API won't throw.
<iank_> TabAtkins: That's in the pending edits.
<iank_> TabAtkins: JS stuff is on a separate layer.
<iank_> dino: What would happen? Ignored?
<iank_> TabAtkins: JS api wins. Treated as the "last" one.
<iank_> dino: If browser only supports JS version, nothing special.
<iank_> smfr: I have another thing related to animating untyped custom properties.
<smfr> https://codepen.io/smfr/pen/JjPerWw
<iank_> smfr: Question is - to do animation of untyped animated propeties, do you need to rerun the style-recalc each frame?
<iank_> TabAtkins: No, it flips 1/2 way through the animation.
<iank_> TabAtkins: All unreg. custom props are discreet.
<iank_> smfr: ok
<iank_> fremy: If you animate the custom property, and use it in another property which animates?
<iank_> emilio: Everyone is different (only FF gets it right?)
<iank_> TabAtkins: We discussed this years ago, there are like 16 options.
<iank_> dbaron: 6.
<iank_> TabAtkins: There were sub-options.
<iank_> majidvp: What happens when you reg. a type for that custom prop while animationing.
<iank_> TabAtkins: Just changes the value of the custom prop.
<iank_> TabAtkins: If that's unclear, happy to add somethign.
<iank_> heycam: Thats different to when you change font-size?
<iank_> TabAtkins: Yes - it changes the value of the property, e.g. from a token-stream to a <length>
<iank_> heycam: In web-anim is it possible to change the from value.
<iank_> TabAtkins: I believe it kicks off a new transition. Not entirely clear how this works.
<iank_> majidvp: web-anim for the duration of the animation, when you start the animtion the curve is computed, but transitions are different.
<iank_> TabAtkins: Sounds like it answers the relevant questions \o/
<iank_> smfr: Can we talk about the status?
<iank_> smfr: Hesitant to implement all the syntaxes.
<iank_> TabAtkins: Isn't that what we do right now?
<iank_> TabAtkins: A handful of primitive types, w/ + and *
<iank_> smfr: I thought it was more that that?
<iank_> TabAtkins: No there isn't the possibility for needing to decide what part of the syntax to match.
<iank_> TabAtkins: 3.1 describes all that you can do.
<iank_> TabAtkins: thing+ | other-thing+ etc,
<iank_> <br type="morning-tea" length="30m">
<majidvp> github: https://github.com//issues/945
<TabAtkins> github: https://github.com//issues/940

Does registering inherit false on a custom property provide any performance benefit?

I have been playing round with registered custom properties as a means of theming in Svelte. The theme is passed down on the context. This theme is then used to set CSS variables that affect a single element:
https://codesandbox.io/s/svelte-theme-components-crt54?fontsize=14&module=%2FButton.svelte

Is my assumption correct that by setting inherit to false we can let the browser know it does not need to recalculate children when a variable on a child element changes?