material-ui
material-ui copied to clipboard
Emotion Global component styles unexpectedly overridden by MUI styles (Next.js, TypeScript, Emotion Engine)
Duplicates
- [x] I have searched the existing issues
Latest version
- [X] I have tested the latest version
Steps to reproduce 🕹
Link to live example: https://github.com/kevinpfox/emotion-proof-of-concept-april
... is clone of - https://github.com/mui/material-ui/tree/master/examples/material-next-ts with as minimal changes as possible to demonstrate the issue.
Current behavior 😯
3px pink border does not render on <Button>
component on this page: pages/about.tsx
border style set here https://github.com/kevinpfox/emotion-proof-of-concept-april/blob/main/pages/about.tsx#L12-L27
Expected behavior 🤔
3px pink border renders on <Button>
component.
Border provided by Emotion <Global>
component in JSX of pages/about.tsx
Expected DOM (something like this) (I manually pushed Emotion Global produced tag down the document DOM in Chrome dev tools)
Similar to what we had previously with MUI V4
Suggested fix from MUI documentation to use
prepend: true
in createCache
from import createCache from '@emotion/cache';
That code is in example and doesn't fix issue https://github.com/kevinpfox/emotion-proof-of-concept-april/blob/main/src/createEmotionCache.ts#L18
Context 🔦
Reason it matters: We would like to use Emotion <Global>
to set all our custom overrides of MUI styles.
This is how we handled it with our current MUI V4 implementation - https://www.babycenter.com
We are switch from MUI V4 to MUI V5 and switching from styled-components to Emotion.
This has become a sticking point, since <StyledEngineProvider injectFirst>
got the desired result with styled-components + MUI V4 setup, but we can not use that context with our upcoming Emotion + MUI V5 setup.
Side note:
The following is a branch of the same demo above, with only difference being addition of <StyledEngineProvider injectFirst>
Everything works great, just the way we want it, but there is the ominous hydration error, making it a no go.
https://github.com/kevinpfox/emotion-proof-of-concept-april/pull/1/files
Your environment 🌎
I worked around this issue by moving/converting all of our old MUI global overrides from a Emotion Global template literal style CSS block (was previously a styled-components Global template literal in MUI V4 version) ...and now all those override items are in a MUI createTheme
block (as in import { createTheme } from '@mui/material/styles';
) employing these sort of overrides....
components: {
MuiButton: {
styleOverrides: {
root: { padding: 0 },
},
},
},
Which is probably the way the MUI team imagined it being done in the first place.
Two years ago we ran into issues using the V4 official override way (import { createTheme } from '@material-ui/core/styles';
), so I choose to override the MUI selectors with a styled-components ThemeProvider template literal block, which worked great, back then.
Might be worth fixing the bug in case other devs have that situation. I get the feeling the MUI team want all of the MUI classes to be easily overridden from anywhere, even from non-MUI Global themes? (not sure). It took awhile to convert the template literal style CSS to the MUI createTheme
JavaScript object style CSS since we have a fairly large codebase.
@kevinpfox Thanks for reporting this, I'll check it out (that hydration error should be fixable)
Would you mind updating the package.json in your repro with more specific versions? Our templates all use latest
, just in case something doesn't match with your actual app 🙂
Thank you for checking it out.
Is <StyledEngineProvider injectFirst>
still a legit solution? For some reason I got the sense it was retired solution. I may have gotten confused though. So many changes from V4 to V5.
I just re-read this https://mui.com/material-ui/guides/interoperability/#css-injection-order and it looks like perhaps it is still a legitimate solution.
I updated the packages to the specific versions I'm working on now.... https://github.com/kevinpfox/emotion-proof-of-concept-april/commit/c1b00b0c9d76963dc238e24946940d0af9b999ca
I tracked back my confusion around these two....
@mui/styles/
vs
@mui/material/styles
It's still not crystal clear to me what is and isn't deprecated.
I just stumbled upon this code comment I wrote in our codebase awhile back....
And then looked up this page (https://mui.com/system/styles/basics/)....
And now I'm staring at this branch of the demo project shared earlier (causes hydration issue)...
https://github.com/kevinpfox/emotion-proof-of-concept-april/pull/1/files
.... and it's becomes pretty apparent how one could get confused about what is and isn't an valid solution currently with MUI5.
I get that StylesProvider
is not the same as StyledEngineProvider
and they come from different imports. But it's pretty easy to see how one could get confused and have uncertainty.
Is the following a potential valid solution (once hydration issue is fixed)?
<StyledEngineProvider injectFirst>
Thanks for the detailed comments. To give some context:
-
@mui/styles
in the legacy, JSS based styling solution. We are not recommending it since v5 - it is not compatible with concurrent rendering, and it will add additional bundle, as it is not based on emotion. - the
<Global />
is intended to use for presets mainly. It will be inserted as first in the head - before any other MUI related styles, so that the component's defined styles will override the preset styles - this is why it is not working in your case. There are some workarounds around this, for e.g. you can use a global selector and bump the specificity of everything defined in yourGlobal
styles, however the theme overrides, usingstyled()
and thesx
prop will likely scale better.
Thanks @mj12albert for looking into the class name mismatch.