-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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
Support CSS variables as theme option #12827
Comments
@abhisheksarka Supporting this would probably mean we support theme colors as CSS variables use case. I have nothing against supporting it, quite the opposite! The limitation right now is that we are performing color manipulation in JavaScript. I'm not sure there is any quick away around this problem. cc @mbrookes. |
It is actually very easy to provide javascript dynamism to CSS variables. And in a way that stays sort of semantic. Say you have a color value graded on an hsla rotation, and that the dynamic part is the H parameter. The static css would be written as such : Now of course javascript cannot go write that in CSS (It can, but it would remove the whole purpose of variables). What you CAN do is use the inheritance hierarchy of the cascade. So therefore, something like And javascript, especially in react, has no problem changing the value of inline styles. It is still an external declaration, as the computed use of the variable value stays in the CSS, but declared by the component as a style configuration, not a declaration. It is often seen as wrong to declare inline styles, but in this case I see it more as a data-attribute use. This can save huge amounts of CSS, and allow a single style declaration to produce multiple results. I have been using this method for a while to produce content with graded, dynamic values, and it is buttery smooth, as the DOM has the final word on its visual configuration, CSS just reads and apply it. There is a caveat with dynamically rendered components not respecting the CSS variables cascade, but there are workarounds around it. |
@rlacorne The original request was to somehow support this as a theme option. Inline styles are a different beast. @oliviertassinari apologies I missed the original name-check. I have no idea how we could reconcile those two concerns. |
It can absolutely be used for themes in the same way. CSS has the :root {} decalaration, it's only a matter of injecting global css variables on the app css :root.
|
We have scripts, that passing all the mui theme consts to css variables on app init and we use them like this: .foo {
padding: calc(var(--spacing-unit) * 2px);
transition: padding calc(var(--transitions-duration-shortest) * 1ms);
} it's great! one problem with some theme-functions. but we have no cases for them for now our current css variable provider looks likeexport function asCssConsts (theme, path) {
const themeConsts = require('./get-set').get(theme, path);
return Object.entries(themeConsts).reduce((res, [key, val]) => {
return Object.assign(res, { ['--' + `${ path }.${ key }`.replace(/\./g, '-')]: val });
}, {});
}
const styles = (theme) => ({
'@global :root': {
'--app-background-color': '#f4f4f4',
...asCssConsts(theme, 'spacing'), // e.g. --spacing-unit
...asCssConsts(theme, 'transitions.duration'), // e.g. --transitions-duration-shortest
...asCssConsts(theme, 'transitions.easing'), // e.g. --transitions-easing-easeInOut
...asCssConsts(theme, 'shape'), // e.g. --transitions-shape-borderRadius
...asCssConsts(theme, 'zIndex'), // e.g. --zIndex-tooltip
// ... |
But It's harder to pass the theme.typography and pallete rule-sets. Css variables connot solve this. So we're use jss with ThemeProvider for that cases |
some css processors allow extending (css-modules we use doesn't support it good :( out of the box) so some mui plugin can expose rule-sets for extending like: .typography-body1 {
color: var(--theme-typography-body1--color);
font-family: var(--theme-typography-body1--fontFamily);
/* ... */
} might be it can be useful with some post-css plugin, that enables extending .myText {
extends: .typography-body1;
color: red;
} |
ok, mui@4 as I see already does something like I propose with extendable rule-sets. But we don't want to use global selectors by default and we're gonna disable this new behaviour, |
hey guys so is there any plan to let us using css variables easily? sorry for bad english |
Do you mean the "unsupported color" warning?
That might bypass the warning, but the js color manipulator functions aren't going to work on |
Hey! Is it possible to evaluate the colors that need to be manipulated via js at the The only other approach I think of would be const root = window.document.documentElement;;
const primaryColor=
root.style.getPropertyValue('--primary-color'); But I think that would mean it is not SSR compatible. |
@HiranmayaGundu |
@oliviertassinari Sorry I think I misunderstood this issue 😅 I think this issue is to allow Whereas what I was thinking was passing |
@HiranmayaGundu This could be cool. I think that we will consider this option for v5 (but there is a IE 11 implication to figure out, which is important for the Chinese market and old UC mobile devices). |
Supporting CSS variables would also open up avoiding flickering of dark mode websites implemented in frameworks like Next.js or Gatsby! (This seems to be the case on the https://material-ui.com/ website itself! Eg. if you set dark mode and refresh, the page will briefly show up in light mode, and then change to dark mode, causing a flicker) Problem demonstrated: https://joshwcomeau.com/css/css-variables-for-react-devs/#dark-mode-flash-fix Solution with CSS variables: https://joshwcomeau.com/gatsby/dark-mode/ Just a thought, could the theme object created by |
@balazsorban44 Agree, we have started to discuss this advantage with @mnajdova. The challenge here is what do we do with color transformation functions? I guess we could have them all generated ahead of time or use prefixing, like |
This comment has been minimized.
This comment has been minimized.
As far as i see, this could be as easy as: import React from 'react';
import { withStyles } from '@material-ui/core';
const cssVariables = (theme) => ({
'@global': {
':root': {
'--color-primary': theme.palette.primary.main,
'--color-secondary': theme.palette.secondary.main,
}
}
});
const RootComponent = () => {
return <div>Whatever...</div>
}
export default withStyles(cssVariables, RootComponent); Having in mind |
@not-only-code That exposes select theme colors as CSS variables, but it's the opposite of what's being asked for. |
Anxiously waiting for this. I have hacked it in for now, but the ability to leverage css --vars as theme variables is huge. |
@oliviertassinari - 5.1 is out - and this didn't make it in. Any idea when? |
@httpete Great point. I'm rephrasing all of this to avoid future confusion, there are no v5.1 plans. cc @mui-org/core. I'm closing the v5.1 milestone. To expand a bit more on how we prioritize/plan. It's mostly on a quarterly basis for mid-term alignments and high-level outcomes, and low-alignment for short-term outcomes. For instance, for Q4 2021, 40% of our time is 1. clean up all the stuff we broke with v5, 2. push unstyled components, 3. push a new design aesthetic with Joy. We have a specific measurable outcome we want to reach 3 months later down the road, and every few months, checking up where we are. We don't clearly define the steps as a team, it's mostly the individual owning the outcome that is accountable for organizing itself. On MUI X, the work is more structured, you take the same as above and add constraints. We define what problem we prioritize for the next 2 weeks in sprints, and how time will be spent during the quarter on all the high-level items. But even then, we don't work with specific release versions. We ship whatever we have on HEAD, following semver. |
I think that "supporting css properties as theme option" isn't a great idea, because theme switching wouldn't work. However, the other way around (supporting theme variables as css properties) is in my opinion the key to the solution. Using this comment #12827 (comment)
I'm using the const setGlobalStyles = (theme: Theme) => (
<GlobalStyles
styles={{
':root': {
'--color-primary': theme.palette.primary.main,
'--color-secondary': theme.palette.secondary.main,
},
}}
/>
) Here's a working demonstration. I synchronize it with the // import lightTheme & darkTheme
const MyApp = () => {
const [theme, setTheme] = useState<Theme>(lightTheme)
return (
<ThemeProvider theme={theme}>
{setGlobalStyles(theme)}
<Button onClick={() => setTheme(darkTheme)}>dark theme</Button>
</ThemeProvider>
)
}
export default MyApp I'm using one more ugly trick to tell my IDE that I defined these css properties: /* globals.css */
.definitions {
--color-primary: unset;
--color-secondary: unset;
} Note that I didn't check yet if it causes flickering with SSR implementations. |
@siriwatknp feel free to unassign yourself if not relevant to your current focus. |
@mbrookes Thanks, this is now on my radar. I will create a proper RFC about adopting CSS variables for mui-material soon. @RemyMachado I think that's a good quick workaround, however, you will still see a flicker when switching between light & dark mode. We have done some POC about how to fix it #27651 and I will create a plan for adding CSS variables to mui-material soon. |
Has the above feature been implemented to the latest release? |
@junlueZH Not yet (but we have created a proposal) and it will be slightly different. I have created a plan for adopting the CSS variables as a feature for |
@siriwatknp The main idea of css variables for me is to use them inside of *.module.css files. This allows me to decrease rerenders because of hook styles changes (maybe they never will but it's still possible) and improve performance. |
@vdpdev Theoretically, I believe that it should work (both client & server-side rendering) because the CSS variables generated from the theme will be attached at the top of the HTML ( However, I am not sure about how to make the development experience better (variable suggestion) for the styling solution like CSS modules, SCSS. But I think this is another topic for improvement. |
I tried to use the var syntax in the Theme:
and TableRow started to bark. If I use a js function to get the value from the global css root and pass that as a #hex it worked. |
Hey everyone, we have the experimental APIs to generate the theme tokens to CSS variables. Please have a look at https://mui.com/material-ui/experimental-api/css-theme-variables/overview/. I'm closing this issue! |
@siriwatknp Any reason this functionality doesn't generate the spacing, transition, etc. variables? |
That'd be the next improvements. |
@siriwatknp thanks. I found the shouldSkipGeneratingVar function and override it to get some more properties generated. One problem I found is that if you're trying to override the primary and secondary colors from the variables with your own colors the elements will flash with the default color before applying yours. |
Please create a new issue and provide a CodeSandbox, I can take a look at it. |
Setting primary/secondary palette colors via Using Anyone got a good solution for this? 🙏 ps. telling users that the html will be larger and therefore the FCP slower is moot when everyone is using brotli/gzip anyways and the size difference is very likely insignificant. |
Can you create a new issue and give some more detail about it? thanks a lot. |
Following these instructions https://mui.com/material-ui/experimental-api/css-theme-variables/customization/#color-schemes const theme = extendTheme({
colorSchemes: {
light: {
palette: {
primary: {
main: "var(--my-color)"
}
}
},
dark: {
palette: {
primary: {
main: "var(--my-color)"
}
}
}
}
}) produces the following error MUI: Unsupported `var(--my-color)` color.
The following formats are supported: #nnn, #nnnnnn, rgb(), rgba(), hsl(), hsla(), color(). Wrapping the values in |
I have the same issue. palette:{
primary: {
light: 'var(--foreground-first-light)',
main: 'var(--foreground-first)',
dark: 'var(--foreground-first-dark)',
contrastText: 'var(--foreground-first-contrastText)',
},
} and when I use I get an error
|
@DGaibor Referencing to other CSS variables is not yet supporting because the |
if i can't use vars in my ThemeProvider config in order not to set the same var that i have in hexcode for my every button - what is the point of all this and does this problem has any workaround? I mean a MUST use hex-code only that I have, and I can't just put my var into rgb(), it just does not make sense |
Supporting CSS variables would:
Problem demonstrated: https://joshwcomeau.com/css/css-variables-for-react-devs/#dark-mode-flash-fix
Solution with CSS variables: https://joshwcomeau.com/gatsby/dark-mode/
Benchmark
The text was updated successfully, but these errors were encountered: