-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for CSS variables in style attributes #6411
Comments
What are your thoughts on using JavaScript for this? Conceptually React’s experimental-and-subject-to-change context feature allows you to define variables local to a subtree of components. Your parent might look like class BlueBar extends Component {
getChildContext() {
return {
color: '#f00'
};
}
render() {
return (
<div>
<Background>
<NotificationBadge />
<SearchBox />
</Background>
</div>
);
}
}
BlueBar.childContextTypes = {
color: PropTypes.string.isRequired
}; and your child components could read it like this: class Background extends Component {
render() {
return (
<div style={{ backgroundColor: this.context.color }}>
{this.props.children}
</div>
);
}
}
Background.contextTypes = {
color: PropTypes.string.isRequired
}; I understand this is orthogonal to whether we want to support CSS variables, but it could be a good solution in the meantime. |
We have a large codebase(user interface for the Vivaldi browser) in Less. I have looked at some JavaScript-ways of managing our styles, but so far we've decided to not make the switch. Using context looks nice, and would solve some issues, but not all. Using CSS variables would let us simplify our existing Less codebase without a full rewrite. |
Thanks for sharing the context (pun totally intended). |
As long as the spec is stable enough (haven't looked at it recently), it seems like this should be doable, but not sure at what cost. Basically we can use
Yea, that's a result of us using innerHTML to do the first render and then updating properties after that. This will stop working in v15, even for initial render, so heads up. |
We're in a bit of a unique position perhaps, since we only need to relate to Chromium. But support for CSS variables is maturing, according to http://caniuse.com/#feat=css-variables. I would not mind setting the variables differently from the rest of the inline style declaration, I would just love a way to do this with React. |
I think the short-term plan for this is probably to just leave the status quo and not change what we do for styles. As we continue to explore js styles, I think we're likely to end up changing how we end up doing styles. For now if you want to use CSS variables you'll want to just break out of the declarative approach and manage setting these yourself with the lifecycle hooks (eg set refs and then in componentDidMount componentDidUpdate, use the ref to call |
By using the lifecycle hooks correctly, I got it working. It does seem to cause trouble with using React style attributes, but setting style with JS instead worked fine. |
From what I understand, the trick is hooking the refs up so that the non-virtual DOM nodes will be known at the time the style is applied. Relevant thread: postcss/postcss-custom-properties#1 |
I've successfully converted most of our internal variables to CSS variables, using a wrapper to calculate them before they're applied. By giving the user control of 4 higher level colors, I can calculate relevant palettes. This allowed for theming our product (https://vivaldi.net/en-US/teamblog/121-snapshot-1-3-501-6-customizable-ui-themes). I insert the variables at the top of each window, and can optionally override them further down the DOM tree. The top component is passed theme as a prop, and the the componentDidUpdate function looks like so:
I found that setting the property would not replace the old one, so it needs to be removed first. The theme prop only contains the changed variables, keeping overhead down. The performance of the variables are good, and it has allowed us to remove a large amount of CSS. |
Having the ability to have https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom#styling This would also solve the issues of
I've looked through the issues here and have seen a bunch of related issues, but the latest Web Components spec has since been updated. What it ends up coming down to is |
Perhaps sanitation via ES2015 tagged template strings could work for parsing styles. A bit more elegant than say, XML CDATA escapes. |
I did this, which can be useful until this is fixed : https://github.com/jide/react-css-variables |
Could still really use this. @jide's solution is great for most cases, but my case is for a Modal that is injected outside of the app. |
For reference, here's a small yet non-trivial use-case. Let's say you want to toggle between light and dark themes for any text nodes in a certain element: const LightDarkSpan = ({ children }) => (
<span style={{
color: 'var(--text-color, black)'
}}>
{children}
</span>
); Then, any parent can set that variable, and it effectively acts as context to any child element that explicitly chooses to use that specific CSS variable: // rendered
<div style={{
backgroundColor: 'black',
'--text-color': 'white'
}}>
<article>
<LightDarkSpan>testing</LightDarkSpan>
</article>
</div> No extra JS indirection needed 👍 cc. @spicyj |
This seems to me like something we may as well support unless @sebmarkbage / @gaearon have an objection. It sounds like it would be only an additional two lines of code in our style logic. |
👍 |
I think we'd want to special case the way we set it based on the key. So we'd have to materialize, compare and inspect the key string. (Un)fortunately we already do that with floats (which already makes everything slower). I guess it's fine. It'll always be a slow-path. If you want to be on the slow-path, sure. |
Curious if @trueadm has done any benchmarking on |
Some relevant benchmarking info done here: https://jsperf.com/dom-style-vs-setproperty Source: https://github.com/elm-lang/virtual-dom/pull/44 It seems to be faster in some environments. |
I ran that benchmark in IE9-11 and in all cases |
Looks like CSS Typed OM is all about those (well typed, lol) strings too so seems pretty future proof direction. |
Furthermore, in regards to Edge/MS, they should be also applying the fast path optimization for |
I created this testcase comparing setProperty and style setter with custom and native properties. Strangely setProperty is faster when using custom properties (Chrome 57.x) which obviously makes me happy. https://jsperf.com/style-setter-vs-setproperty I looked left and right to check if I messed anything up in the test because the difference in speed is so immense. Feedback welcome. |
I looked into it and I reckon there's still an issue with this. So if the parent set a variable that one child want to use is fine. But if that child imports a react component that is using the same variable name, that would be affected as well. Web Components solve this issue cause they are isolated by default... Is there a way we can get React to create custom elements if needed? |
That should solve isolation for styles... |
This is no different than name collisions on It's also not hard to namespace or obfuscate (a la CSS Modules) CSS variables. It's just a string, after all, e.g.: |
Maybe obfuscate could be a way, but is not really standard... |
@LucaColonnello This is just the way it works. It's the same issue with components and classnames.
Wait what? Where did you read that? |
The standard is now about using web components in order to have an isolated and scoped style using If I'm going to obfuscate the variables my component is using, it would be hard to change from outside the variable value when my component is packed and compiled into node modules. Obfuscation is a good technique we use for example with css-modules, but the standard is coming with a build in solution foe conflict that is scoped CSS. I'm trying to say that a solution already exists in the browser, although we can do what we prefer and what's more sensitive for us. Correct me if I'm wrong anyway :) |
I just don't think this is related to the actual feature request to simply allow the usage. The request is a feature. You are talking about scoped styles for webcomponents. |
Yeah yeah that's true. This was to just to say that we have not everything we need for CSS variables also with this feature. But is a feature I'd like to have anyway... |
I'm trying this but the CSS Custom prop doesn't get applied? |
It wasn't released yet |
15.5.4 (April 11, 2017) The PR was merged on April, 20 |
@FezVrasta I forked your pen to 15.5.4: https://codepen.io/thejase/pen/owvQNe |
@TheJase See my comment. 15.5.4 was released 0n April 11th. The merge was done 9 days later. |
@pixelass Ah, now I understand. Sorry, wasn't thinking straight. Nonetheless, I had to correct a selector on the previous fork ( |
So we have to wait until the next release right? |
This is in 15.6.0-rc.1 (release candidate on npm) and will be in 15.6 final. |
Thanks @spicyj! |
I'm trying to use the variables in a boolean way to change some things in CSS: .foo {
height: calc(46px * var(--open))
}
.bar {
transform: translateY(calc(46px * (1 - var(--open))))
} The ideal way would be to set I manage to do it with: <div style={{'--open': `calc(${this.state.open * 1})`}}>
...
</div> Is there a way to disable units in from inline styles? |
I think you can pass them as string |
@FezVrasta doesn't work, but I get the warning:
So I think I will have to wait 😋 |
Hi guys, sorry but i have a problem. I'm trying to make my application with 2 themes but without fortune. This is the method i call in componentDidMount of my application component.
Where value.prop === '--color-01' and value.value(i will change) is This is my default theme variables: `:root { --color-01: #192635; }` Thanks in advance and have a nice day. |
CSS variables is now supported in Chromium, which we use for rendering. They enable us to write cleaner, more flexible code. Sadly, I cannot seem to use them in React without resorting to various tricks. Ideally, I would like to be able to use them like
<div style={{"--color": "hotpink"}} />
, which would make the variable available inside the scope of the div.I am able to add them using the following syntax
<div style={{["--color"]: "hotpink"}} />
, but then they aren't updated if I try assigning a new value—which ruins much of the point of using a variable.I am able to add and remove them using ReactDOM and
ReactDOM.findDOMNode(this).style.setProperty("--color", "hotpink")
, but that gets it out of sync with the DOM updates, in addition to not being pretty.If there are any questions on the usefulness of CSS variables I'll be more than happy to explain.
The text was updated successfully, but these errors were encountered: