MUI v5 Emotion Migration: Theme Override Precedence During JSS Coexistence
0 reputation · 23 Jul 2022, 09:59 UTC
0 reputation · 23 Jul 2022, 09:59 UTC
When incrementally migrating a large codebase from MUI v4 (JSS) to v5 (Emotion), the compatibility layer allows both styling engines to operate simultaneously. The goal is to progressively convert theme-level component overrides in createTheme to the new Emotion-based styled() API without a full rewrite.
The migration path introduces uncertainty around precedence: theme overrides defined in createTheme (v5 style) may conflict with lingering makeStyles or withStyles injections (v4 style) targeting the same component slots. Additionally, the sx prop resolves against the v5 theme object, but its generated Emotion classes must not collide with existing JSS class names in the DOM. Bundle size impact from dual-engine runtime is a documented constraint.
How does MUI v5 resolve specificity when a component slot receives styles from both a v4 JSS class and a v5 theme override simultaneously? What is the recommended sequence for converting createTheme overrides to styled() utilities to avoid regression during the coexistence window? Does the CssVarsProvider experimental API alter this precedence model when CSS variables are enabled?
31275 reputation · 23 Jul 2022, 13:21 UTC
When MUI v4 JSS and MUI v5 Emotion run together, precedence for the same slot is decided by CSS cascade order, not by engine. At equal specificity the rule that appears later in the document <head> wins. MUI v5 theme overrides and the sx prop produce Emotion classes. makeStyles/withStyles produce JSS classes. If Emotion <style> tags are injected after JSS tags, v5 theme overrides and sx will override v4 JSS at equal specificity. If the injection order is reversed, JSS wins.
createTheme component overrides and sx generate Emotion classes.@mui/styles uses JSS and injects its own <style> tags.StyledEngineProvider controls Emotion injection order relative to other engines. This is the documented mechanism for co-existence.CssVarsProvider changes value resolution to CSS variables. It does not change cascade precedence between Emotion and JSS.Injection order is the practical lever. In a typical incremental migration the intent is for v5 styles to win. That requires Emotion styles to be injected after JSS styles in the DOM. The exact order depends on provider placement and render timing, not on the engine name.
Specificity conflicts can still occur. JSS rules using !important or deeply nested selectors can beat Emotion rules even when Emotion is later in the head. sx tends to generate classes that are placed late in the cascade, which is why it often appears to override both JSS and theme-level overrides.
StyledEngineProvider and verify the DOM order of <style> tags. Keep Emotion after JSS for v5 to win.createTheme object first. Do not duplicate the same overrides in makeStyles. This centralizes the source of truth in the v5 theme.makeStyles/withStyles with styled() or sx. Keep the v5 theme override in place until the component is fully migrated, then remove the legacy JSS.<style> tag.Enabling CssVarsProvider does not alter the cascade precedence model between JSS and Emotion. It changes how theme values are accessed, via CSS variables, and can reduce runtime specificity churn, but the winner is still determined by DOM order and specificity.
<head>. Confirm Emotion <style data-emotion> tags appear after JSS <style data-jss> tags for the component under test.<style> tag.Assumption: you are using @mui/material v5 with @mui/styles for legacy JSS and StyledEngineProvider is present. If injectFirst is set, the injection order flips and the recommendation changes.
One missing diagnostic that changes the recommendation: is StyledEngineProvider injectFirst currently true or false in your app, and is CssVarsProvider enabled? The desired precedence for v5 over v4 requires Emotion to be injected after JSS, which is the opposite of the injectFirst compatibility setting used when you want v4 to remain dominant.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.