How to Configure Emotion (styled-engine) with Material-UI

Material-UI ships with Emotion as its default styling engine through the @mui/styled-engine package, requiring zero configuration for standard usage while providing StyledEngineProvider props to control injection order, CSS cascade layers, and custom caches.

Material-UI (MUI) leverages Emotion as its default CSS-in-JS solution, wrapping it in the @mui/styled-engine package to power the styled() API and theme system. When you install @mui/material, the styling engine is automatically included as a dependency, making it possible to configure Emotion with Material-UI for advanced scenarios like server-side rendering or CSS layer ordering. This guide examines the implementation details found in the mui/material-ui repository to show you exactly how to customize the Emotion integration using StyledEngineProvider.

Default Configuration (Zero Setup Required)

When you run npm install @mui/material, you automatically receive @mui/styled-engine as a transitive dependency. This package is a thin wrapper around @emotion/react that re-exports Emotion’s utilities (styled, css, keyframes, GlobalStyles) along with MUI-specific helpers.

The default export in packages/mui-styled-engine/src/index.js re-exports everything from Emotion, which is why import { styled } from '@mui/material/styles' works immediately without additional setup.

import { Button, ThemeProvider, createTheme } from '@mui/material';

const theme = createTheme();

export default function SimpleApp() {
  return (
    <ThemeProvider theme={theme}>
      <Button variant="contained">Hello</Button>
    </ThemeProvider>
  );
}

Controlling Style Injection Order with injectFirst

To ensure Material-UI styles are inserted before your own CSS (giving your styles higher specificity), wrap your application with StyledEngineProvider and set the injectFirst prop. According to the source in packages/mui-styled-engine/src/StyledEngineProvider/StyledEngineProvider.js, this prop forces Emotion to prepend its style tags using prepend: true.

import { StyledEngineProvider, ThemeProvider, createTheme } from '@mui/material';

const theme = createTheme();

export default function App() {
  return (
    <StyledEngineProvider injectFirst>
      <ThemeProvider theme={theme}>
        {/* Your components */}
      </ThemeProvider>
    </StyledEngineProvider>
  );
}

Enabling CSS Cascade Layers

The enableCssLayer prop wraps all generated MUI CSS in a @layer mui rule, allowing you to control cascade order using standard CSS layer syntax. This is implemented in the same StyledEngineProvider.js file and is useful when integrating with Tailwind CSS or other utility-first frameworks.

import { StyledEngineProvider, GlobalStyles } from '@mui/material';

export default function App() {
  return (
    <StyledEngineProvider enableCssLayer>
      <GlobalStyles
        styles={{
          body: { margin: 0, fontFamily: 'Roboto, Arial, sans-serif' },
        }}
      />
      {/* Application content */}
    </StyledEngineProvider>
  );
}

Providing a Custom Emotion Cache (SSR)

For server-side rendering or to specify a custom cache key, pass a manually created Emotion cache to StyledEngineProvider. Create the cache using createCache from @emotion/cache and configure options like key (to namespace data attributes) and prepend (to control DOM insertion).

// cache.js
import createCache from '@emotion/cache';

export const clientCache = createCache({ key: 'mui', prepend: true });
// App.tsx
import { StyledEngineProvider, ThemeProvider, createTheme } from '@mui/material';
import { clientCache } from './cache';

const theme = createTheme();

export default function MyApp({ children }) {
  return (
    <StyledEngineProvider cache={clientCache}>
      <ThemeProvider theme={theme}>
        {children}
      </ThemeProvider>
    </StyledEngineProvider>
  );
}

The provider stores this cache in React’s ThemeContext, which all MUI styling utilities consume via useContext(ThemeContext).

Switching to Styled Components

To replace Emotion with styled-components, alias @mui/styled-engine to @mui/styled-engine-sc in your bundler configuration. This resolution instructs Material-UI to import the styled-components implementation instead of the default Emotion wrapper.

Webpack configuration:

// webpack.config.js
module.exports = {
  resolve: {
    alias: {
      '@mui/styled-engine': '@mui/styled-engine-sc',
    },
  },
};

Package.json resolution (Yarn):

{
  "resolutions": {
    "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest"
  }
}

Refer to the docs/data/material/integrations/styled-components/styled-components.md file in the repository for the complete step-by-step guide.

Summary

  • Default behavior: Installing @mui/material automatically includes @mui/styled-engine (Emotion) with no configuration required.
  • Injection order: Use <StyledEngineProvider injectFirst> to prepend MUI styles before other CSS in the document head.
  • CSS layers: Enable <StyledEngineProvider enableCssLayer> to wrap styles in @layer mui for cascade control.
  • Custom caching: Pass a createCache instance to the cache prop for SSR, custom keys, or specific DOM containers.
  • Alternative engines: Alias @mui/styled-engine to @mui/styled-engine-sc to use styled-components instead of Emotion.

Frequently Asked Questions

Do I need to install Emotion separately when using Material-UI?

No. Emotion is included as a dependency of @mui/material through the @mui/styled-engine package. You only need to install Emotion separately if you are using it directly for custom styling outside of MUI components.

How do I fix CSS injection order conflicts with Material-UI?

Wrap your application with StyledEngineProvider and set the injectFirst prop. This forces Emotion to insert <style> tags at the beginning of the document head, ensuring your custom CSS or third-party styles loaded later take precedence.

Can I use Material-UI with styled-components instead of Emotion?

Yes. Install @mui/styled-engine-sc and styled-components, then configure your bundler to resolve @mui/styled-engine to @mui/styled-engine-sc. After the alias is set, all MUI components will use the styled-components engine instead of Emotion.

What is the purpose of the enableCssLayer prop in StyledEngineProvider?

The enableCssLayer prop wraps all Material-UI generated CSS in a @layer mui block. This allows you to define explicit layer ordering in your CSS (e.g., @layer reset, base, mui, utilities) to control which styles take precedence without relying on specificity hacks.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →