Preact: Add support for CSS Custom Properties

Created on 24 Apr 2017  路  10Comments  路  Source: preactjs/preact

Cross-references with React:

React will soon be able to support CSS Custom Properties (CSS Variables) by using .style.setProperty(<prop>, <value>) instead of directly modifying .style.<prop> = <value> for custom properties (detected by seeing if the property starts with two dashes, e.g., --foo-bar).

It seems that, for objects passed into the style attribute of Preact components, this is currently not the case, as it is still directly setting the style properties: https://github.com/developit/preact/blob/9e1dd185bb1d6505c35477d8101c886c25dc51c8/src/dom/index.js#L57

Furthermore, the use of .style.setProperty(prop, value) seems to be _much_ faster in most environments (except for IE9-11, where it is slightly slower): https://jsperf.com/dom-style-vs-setproperty - shouldn't matter anyway if you choose to use .setProperty for only custom properties.

The end-goal is to have this work:

<div style={{ '--foo': 'green', color: 'var(--foo, red)' }}> 
  ...
</div>

What do you think? 馃槃 It's a fairly minor change and I can make a PR if needed.

discussion enhancement has fix help wanted in X

Most helpful comment

@developit any news on this feature? I saw the PR got out of date with master...

If there's anything I can do to help would love to as I just found myself looking for this feature/wishing I could set variables inline this morning

All 10 comments

Ah yeah I've been meaning to investigate this! Since this is Preact and every byte is slaved over, what do you think about _always_ using style.setProperty() on the line you linked to?

- node.style[i] = /* snip */ value[i];
+ node.style.setProperty(i, /* snip */ value[i]);

It seems like that would enable CSS Custom Properties and even improve perf at the same time, and the cost would be really small. Thoughts?

(edit: presumably we'd need to switch style.foo='' to style.removeProperty('foo') too?)

I think it's a 馃挴 good idea - there's only one downside that the React team ran into - you would have to use the normal, hyphenated CSS property names instead of the camelCase property names:

// this won't work
node.style.setProperty('backgroundColor', 'green');

// this will work
node.style.setProperty('background-color', 'green');

This means that when passing in styles as objects, such as:

<div style={{ backgroundColor: 'green' }} />

you'd have to do some mapping or normalization of the property name to get the hyphenated name. Or you can just always require the hyphenated name -- it would just be a breaking change, though.

ahhh interesting... probably have to keep react compat there.
you wouldn't happen to know if style.cssText supports custom properties would you?

node.style.cssText = '--foo: green; background-color: var(--foo, red);'

It does on Chrome, FireFox, Safari (haven't tested Edge yet)

Does work on Edge.

Interesting - so it's possible serializing to cssText could solve this. I was considering switching back to serialization in order to lighten up the object diff we currently have to do, which is theoretically faster because it sets single properties, but in reality the object traversal cost seems to outweigh any benefit.

Is there any way I can help on this @developit? If you tell me which strategy to take I'd be happy to open a PR.

@tkh44 It might be safest to use the same implementation that Facebook used (at least for starters): https://github.com/facebook/react/pull/9302

@developit any news on this feature? I saw the PR got out of date with master...

If there's anything I can do to help would love to as I just found myself looking for this feature/wishing I could set variables inline this morning

This feature has just landed in master via #1302 :tada:

Was this page helpful?
0 / 5 - 0 ratings