# Tailwind CSS v4 integration

Learn how to use Material UI with Tailwind CSS v4.

## Overview

There are two steps to integrate Tailwind CSS v4 with Material UI:

1. Configure the styles to generate with the `@layer` directive.
2. Set up the layer order so that `mui` comes before the `utilities` layer, allowing Tailwind CSS classes to override Material UI styles.

The instructions below detail how to achieve this using common React frameworks.

:::success
Use the [Material UI + Tailwind CSS agent skill](https://github.com/mui/material-ui/tree/master/skills/material-ui-tailwind) to give your AI coding assistant full context on this integration, including CSS layer ordering, `enableCssLayer`, and Tailwind class overrides.
:::

### Next.js App Router

To integrate Tailwind CSS v4 with Material UI in a Next.js App Router project, start by configuring Material UI with Next.js in the [App Router integration guide](/material-ui/integrations/nextjs/#app-router).
Then follow these steps:

1. Enable the [CSS layer feature](/material-ui/integrations/nextjs/#using-other-styling-solutions) in the root layout:

```tsx title="src/app/layout.tsx"
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';

export default function RootLayout() {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <AppRouterCacheProvider options={{ enableCssLayer: true }}>
          {/* Your app */}
        </AppRouterCacheProvider>
      </body>
    </html>
  );
}
```

2. Configure the layer order in the Tailwind CSS file:

```css title="src/app/global.css"
@layer theme, base, mui, components, utilities;
@import 'tailwindcss';
```

### Next.js Pages Router

To integrate Tailwind CSS v4 with Material UI in a Next.js Pages Router project, start by configuring Material UI with Next.js in the [Pages Router integration guide](/material-ui/integrations/nextjs/#pages-router).
Then follow these steps:

1. Create a shared Emotion cache (required for SSR + hydration)

   Material UI relies on Emotion for styling.
   To avoid hydration mismatches, the same Emotion cache instance and configuration must be used on both the server and the client.

   Create a shared cache:

   ```tsx title="src/createEmotionCache.js"
   import { createEmotionCache } from '@mui/material-nextjs/v15-pagesRouter';

   export const emotionCache = createEmotionCache({ enableCssLayer: true });
   ```

   > `enableCssLayer: true` ensures Material UI styles are wrapped in `@layer mui`, which allows Tailwind CSS v4 utilities to override them predictably.

2. Enable the [CSS layer feature](/material-ui/integrations/nextjs/#configuration-2) in a custom `_document`:

```tsx title="pages/_document.tsx"
import { documentGetInitialProps } from '@mui/material-nextjs/v15-pagesRouter';
import { emotionCache } from '../src/createEmotionCache';
// ...

MyDocument.getInitialProps = async (ctx: DocumentContext) => {
  const finalProps = await documentGetInitialProps(ctx, {
    emotionCache,
  });
  return finalProps;
};
```

3. Configure the global Tailwind CSS file:

```css title="styles/global.css"
@import 'tailwindcss';
```

4. Configure the layer order with the `GlobalStyles` component—it must be the first child of the `AppCacheProvider`:

```tsx title="pages/_app.tsx"
import '../styles/global.css';
import { AppCacheProvider } from '@mui/material-nextjs/v15-pagesRouter';
import GlobalStyles from '@mui/material/GlobalStyles';
import { emotionCache } from '../src/createEmotionCache';

export default function MyApp(props: AppProps) {
  const { Component, pageProps } = props;
  return (
    <AppCacheProvider emotionCache={emotionCache}>
      <GlobalStyles styles="@layer theme, base, mui, components, utilities;" />
      {/* Your app */}
    </AppCacheProvider>
  );
}
```

### Vite.js or any other SPA

To integrate Tailwind CSS v4 with Material UI in a Vite-based app, make the following changes in `src/main.tsx`:

1. Pass the `enableCssLayer` prop to the `StyledEngineProvider` component.
2. Configure the layer order with the `GlobalStyles` component.

```tsx title="main.tsx"
import { StyledEngineProvider } from '@mui/material/styles';
import GlobalStyles from '@mui/material/GlobalStyles';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <StyledEngineProvider enableCssLayer>
      <GlobalStyles styles="@layer theme, base, mui, components, utilities;" />
      {/* Your app */}
    </StyledEngineProvider>
  </React.StrictMode>,
);
```

## Tailwind CSS IntelliSense for VS Code

The official [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) extension requires extra configuration to work properly when customizing the interior slots of Material UI components.
After installing the extension, add the following line to your [VS Code `settings.json`](https://code.visualstudio.com/docs/configure/settings#_settings-json-file) file:

```json
{
  // ...config
  "tailwindCSS.experimental.classRegex": [["className\\s*:\\s*['\"]([^'\"]*)['\"]"]]
}
```

Now you should see the autocomplete and syntax highlighting features when using the `slotProps` prop, as shown in the screenshot below:

![A preview of Tailwind CSS Intellisense](/static/material-ui/tailwind-intellisense.jpg)

## Usage

- Use the `className` prop to apply Tailwind CSS classes to the root element of the component.
- Use `slotProps.{slotName}.className` to apply Tailwind CSS classes to a component's [interior slots](/material-ui/customization/overriding-component-structure/#interior-slots).

```tsx
import FormControl from '@mui/material/FormControl';
import InputLabel from '@mui/material/InputLabel';
import Input from '@mui/material/Input';
import FormHelperText from '@mui/material/FormHelperText';

export default function TextFieldTailwind() {
  return (
    <FormControl>
      <InputLabel
        shrink
        htmlFor="component-outlined"
        className="relative top-0 left-0 transform-none text-sm font-medium text-neutral-800 dark:text-neutral-200 pointer-events-auto mb-0.5"
      >
        Name
      </InputLabel>
      <Input
        id="component-outlined"
        placeholder="Type your name"
        slotProps={{
          root: {
            className:
              'mt-0 -ml-0.5 px-2 h-10 border-1 border-neutral-300 dark:border-neutral-700 rounded-md has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm before:hidden after:hidden',
          },
          input: {
            className:
              'placeholder:opacity-100 placeholder:text-neutral-400 dark:placeholder:text-neutral-500',
          },
        }}
      />
      <FormHelperText className="ml-0">Some important helper text</FormHelperText>
    </FormControl>
  );
}

```

## Extend Material UI classes

If you want to use Material UI theme tokens in your Tailwind CSS classes, copy the snippet below into your CSS file.

```css title="global.css"
@layer theme, base, mui, components, utilities;
@import 'tailwindcss';

@theme inline {
  /* Material UI typography */
  --font-h1: var(--mui-font-h1);
  --font-h2: var(--mui-font-h2);
  --font-h3: var(--mui-font-h3);
  --font-h4: var(--mui-font-h4);
  --font-h5: var(--mui-font-h5);
  --font-h6: var(--mui-font-h6);
  --font-subtitle1: var(--mui-font-subtitle1);
  --font-subtitle2: var(--mui-font-subtitle2);
  --font-body1: var(--mui-font-body1);
  --font-body2: var(--mui-font-body2);
  --font-button: var(--mui-font-button);
  --font-caption: var(--mui-font-caption);
  --font-overline: var(--mui-font-overline);

  --letter-spacing-h1: -0.01562em;
  --letter-spacing-h2: -0.00833em;
  --letter-spacing-h4: 0.00735em;
  --letter-spacing-h6: 0.0075em;
  --letter-spacing-body1: 0.00938em;
  --letter-spacing-body2: 0.01071em;

  /* Material UI breakpoints */
  --breakpoint-sm: 37.5rem; /* 600px */
  --breakpoint-md: 56.25rem; /* 900px */
  --breakpoint-lg: 75rem; /* 1200px */
  --breakpoint-xl: 96rem; /* 1536px */
  --breakpoint-2xl: 120rem; /* 1920px */

  /* Material UI theme colors */
  --color-primary: var(--mui-palette-primary-main);
  --color-primary-light: var(--mui-palette-primary-light);
  --color-primary-dark: var(--mui-palette-primary-dark);
  --color-primary-contrast: var(--mui-palette-primary-contrastText);

  --color-secondary: var(--mui-palette-secondary-main);
  --color-secondary-light: var(--mui-palette-secondary-light);
  --color-secondary-dark: var(--mui-palette-secondary-dark);
  --color-secondary-contrast: var(--mui-palette-secondary-contrastText);

  /* Material UI status colors */
  --color-info: var(--mui-palette-info-main);
  --color-info-light: var(--mui-palette-info-light);
  --color-info-dark: var(--mui-palette-info-dark);
  --color-info-contrast: var(--mui-palette-info-contrastText);

  --color-error: var(--mui-palette-error-main);
  --color-error-light: var(--mui-palette-error-light);
  --color-error-dark: var(--mui-palette-error-dark);
  --color-error-contrast: var(--mui-palette-error-contrastText);

  --color-success: var(--mui-palette-success-main);
  --color-success-light: var(--mui-palette-success-light);
  --color-success-dark: var(--mui-palette-success-dark);
  --color-success-contrast: var(--mui-palette-success-contrastText);

  --color-warning: var(--mui-palette-warning-main);
  --color-warning-light: var(--mui-palette-warning-light);
  --color-warning-dark: var(--mui-palette-warning-dark);
  --color-warning-contrast: var(--mui-palette-warning-contrastText);

  /* Material UI text & common colors */
  --color-text-primary: var(--mui-palette-text-primary);
  --color-text-secondary: var(--mui-palette-text-secondary);
  --color-text-disabled: var(--mui-palette-text-disabled);
  --color-common-background: var(--mui-palette-common-background);
  --color-common-onBackground: var(--mui-palette-common-onBackground);
  --color-divider: var(--mui-palette-divider);

  /* Material UI background colors */
  --color-background-default: var(--mui-palette-background-default);
  --color-background-paper: var(--mui-palette-background-paper);

  /* Material UI action colors */
  --color-action-active: var(--mui-palette-action-active);
  --color-action-hover: var(--mui-palette-action-hover);
  --color-action-selected: var(--mui-palette-action-selected);
  --color-action-disabled: var(--mui-palette-action-disabled);
  --color-action-focus: var(--mui-palette-action-focus);

  /* Material UI gray scale */
  --color-gray-50: var(--mui-palette-grey-50);
  --color-gray-100: var(--mui-palette-grey-100);
  --color-gray-200: var(--mui-palette-grey-200);
  --color-gray-300: var(--mui-palette-grey-300);
  --color-gray-400: var(--mui-palette-grey-400);
  --color-gray-500: var(--mui-palette-grey-500);
  --color-gray-600: var(--mui-palette-grey-600);
  --color-gray-700: var(--mui-palette-grey-700);
  --color-gray-800: var(--mui-palette-grey-800);
  --color-gray-900: var(--mui-palette-grey-900);
  --color-gray-A100: var(--mui-palette-grey-A100);
  --color-gray-A200: var(--mui-palette-grey-A200);
  --color-gray-A400: var(--mui-palette-grey-A400);
  --color-gray-A700: var(--mui-palette-grey-A700);

  /* Material UI Component Colors */
  /* Alert */
  --color-Alert-error: var(--mui-palette-Alert-errorColor);
  --color-Alert-info: var(--mui-palette-Alert-infoColor);
  --color-Alert-success: var(--mui-palette-Alert-successColor);
  --color-Alert-warning: var(--mui-palette-Alert-warningColor);
  --color-Alert-errorFilled: var(--mui-palette-Alert-errorFilledBg);
  --color-Alert-infoFilled: var(--mui-palette-Alert-infoFilledBg);
  --color-Alert-successFilled: var(--mui-palette-Alert-successFilledBg);
  --color-Alert-warningFilled: var(--mui-palette-Alert-warningFilledBg);
  --color-Alert-errorFilledColor: var(--mui-palette-Alert-errorFilledColor);
  --color-Alert-infoFilledColor: var(--mui-palette-Alert-infoFilledColor);
  --color-Alert-successFilledColor: var(--mui-palette-Alert-successFilledColor);
  --color-Alert-warningFilledColor: var(--mui-palette-Alert-warningFilledColor);
  --color-Alert-errorStandard: var(--mui-palette-Alert-errorStandardBg);
  --color-Alert-infoStandard: var(--mui-palette-Alert-infoStandardBg);
  --color-Alert-successStandard: var(--mui-palette-Alert-successStandardBg);
  --color-Alert-warningStandard: var(--mui-palette-Alert-warningStandardBg);
  --color-Alert-errorIcon: var(--mui-palette-Alert-errorIconColor);
  --color-Alert-infoIcon: var(--mui-palette-Alert-infoIconColor);
  --color-Alert-successIcon: var(--mui-palette-Alert-successIconColor);
  --color-Alert-warningIcon: var(--mui-palette-Alert-warningIconColor);

  /* AppBar */
  --color-AppBar-default: var(--mui-palette-AppBar-defaultBg);

  /* Avatar */
  --color-Avatar-default: var(--mui-palette-Avatar-defaultBg);

  /* Button */
  --color-Button-inheritContained: var(--mui-palette-Button-inheritContainedBg);
  --color-Button-inheritContainedHover: var(
    --mui-palette-Button-inheritContainedHoverBg
  );

  /* Chip */
  --color-Chip-defaultBorder: var(--mui-palette-Chip-defaultBorder);
  --color-Chip-defaultAvatar: var(--mui-palette-Chip-defaultAvatarColor);
  --color-Chip-defaultIcon: var(--mui-palette-Chip-defaultIconColor);

  /* FilledInput */
  --color-FilledInput-bg: var(--mui-palette-FilledInput-bg);
  --color-FilledInput-hover: var(--mui-palette-FilledInput-hoverBg);
  --color-FilledInput-disabled: var(--mui-palette-FilledInput-disabledBg);

  /* LinearProgress */
  --color-LinearProgress-primary: var(--mui-palette-LinearProgress-primaryBg);
  --color-LinearProgress-secondary: var(--mui-palette-LinearProgress-secondaryBg);
  --color-LinearProgress-error: var(--mui-palette-LinearProgress-errorBg);
  --color-LinearProgress-info: var(--mui-palette-LinearProgress-infoBg);
  --color-LinearProgress-success: var(--mui-palette-LinearProgress-successBg);
  --color-LinearProgress-warning: var(--mui-palette-LinearProgress-warningBg);

  /* Skeleton */
  --color-Skeleton-bg: var(--mui-palette-Skeleton-bg);

  /* Slider */
  --color-Slider-primary: var(--mui-palette-Slider-primaryTrack);
  --color-Slider-secondary: var(--mui-palette-Slider-secondaryTrack);
  --color-Slider-error: var(--mui-palette-Slider-errorTrack);
  --color-Slider-info: var(--mui-palette-Slider-infoTrack);
  --color-Slider-success: var(--mui-palette-Slider-successTrack);
  --color-Slider-warning: var(--mui-palette-Slider-warningTrack);

  /* SnackbarContent */
  --color-SnackbarContent-bg: var(--mui-palette-SnackbarContent-bg);
  --color-SnackbarContent-text: var(--mui-palette-SnackbarContent-color);

  /* SpeedDialAction */
  --color-SpeedDialAction-fabHover: var(--mui-palette-SpeedDialAction-fabHoverBg);

  /* StepConnector & StepContent */
  --color-StepConnector-border: var(--mui-palette-StepConnector-border);
  --color-StepContent-border: var(--mui-palette-StepContent-border);

  /* Switch */
  --color-Switch-default: var(--mui-palette-Switch-defaultColor);
  --color-Switch-defaultDisabled: var(--mui-palette-Switch-defaultDisabledColor);
  --color-Switch-primaryDisabled: var(--mui-palette-Switch-primaryDisabledColor);
  --color-Switch-secondaryDisabled: var(--mui-palette-Switch-secondaryDisabledColor);
  --color-Switch-errorDisabled: var(--mui-palette-Switch-errorDisabledColor);
  --color-Switch-infoDisabled: var(--mui-palette-Switch-infoDisabledColor);
  --color-Switch-successDisabled: var(--mui-palette-Switch-successDisabledColor);
  --color-Switch-warningDisabled: var(--mui-palette-Switch-warningDisabledColor);

  /* TableCell */
  --color-TableCell-border: var(--mui-palette-TableCell-border);

  /* Tooltip */
  --color-Tooltip-bg: var(--mui-palette-Tooltip-bg);

  /* Material UI shadows */
  --shadow-1: var(--mui-shadows-1);
  --shadow-2: var(--mui-shadows-2);
  --shadow-3: var(--mui-shadows-3);
  --shadow-4: var(--mui-shadows-4);
  --shadow-5: var(--mui-shadows-5);
  --shadow-6: var(--mui-shadows-6);
  --shadow-7: var(--mui-shadows-7);
  --shadow-8: var(--mui-shadows-8);
  --shadow-9: var(--mui-shadows-9);
  --shadow-10: var(--mui-shadows-10);
  --shadow-11: var(--mui-shadows-11);
  --shadow-12: var(--mui-shadows-12);
  --shadow-13: var(--mui-shadows-13);
  --shadow-14: var(--mui-shadows-14);
  --shadow-15: var(--mui-shadows-15);
  --shadow-16: var(--mui-shadows-16);
  --shadow-17: var(--mui-shadows-17);
  --shadow-18: var(--mui-shadows-18);
  --shadow-19: var(--mui-shadows-19);
  --shadow-20: var(--mui-shadows-20);
  --shadow-21: var(--mui-shadows-21);
  --shadow-22: var(--mui-shadows-22);
  --shadow-23: var(--mui-shadows-23);
  --shadow-24: var(--mui-shadows-24);

  /* Material UI opacity */
  --opacity-activated: calc(100% * var(--mui-palette-action-activatedOpacity));
  --opacity-disabled: calc(100% * var(--mui-palette-action-disabledOpacity));
  --opacity-focus: calc(100% * var(--mui-palette-action-focusOpacity));
  --opacity-hover: calc(100% * var(--mui-palette-action-hoverOpacity));
  --opacity-selected: calc(100% * var(--mui-palette-action-selectedOpacity));

  /* Material UI overlays */
  --overlay-1: var(--mui-overlays-1);
  --overlay-2: var(--mui-overlays-2);
  --overlay-3: var(--mui-overlays-3);
  --overlay-4: var(--mui-overlays-4);
  --overlay-5: var(--mui-overlays-5);
  --overlay-6: var(--mui-overlays-6);
  --overlay-7: var(--mui-overlays-7);
  --overlay-8: var(--mui-overlays-8);
  --overlay-9: var(--mui-overlays-9);
  --overlay-10: var(--mui-overlays-10);
  --overlay-11: var(--mui-overlays-11);
  --overlay-12: var(--mui-overlays-12);
  --overlay-13: var(--mui-overlays-13);
  --overlay-14: var(--mui-overlays-14);
  --overlay-15: var(--mui-overlays-15);
  --overlay-16: var(--mui-overlays-16);
  --overlay-17: var(--mui-overlays-17);
  --overlay-18: var(--mui-overlays-18);
  --overlay-19: var(--mui-overlays-19);
  --overlay-20: var(--mui-overlays-20);
  --overlay-21: var(--mui-overlays-21);
  --overlay-22: var(--mui-overlays-22);
  --overlay-23: var(--mui-overlays-23);
  --overlay-24: var(--mui-overlays-24);
}

/* Material UI base styles */
@layer base {
  h1 {
    font: var(--mui-font-h1);
    letter-spacing: -0.01562em;
  }
  h2 {
    font: var(--mui-font-h2);
    letter-spacing: -0.00833em;
  }
  h3 {
    font: var(--mui-font-h3);
  }
  h4 {
    font: var(--mui-font-h4);
    letter-spacing: 0.00735em;
  }
  h5 {
    font: var(--mui-font-h5);
  }
  h6 {
    font: var(--mui-font-h6);
    letter-spacing: 0.0075em;
  }
  p {
    font: var(--mui-font-body1);
    letter-spacing: 0.00938em;
  }
  span {
    font: var(--mui-font-body2);
    letter-spacing: 0.01071em;
  }
}

/* Material UI typography utilities */
@utility typography-* {
  font: --value(--font-*);
}

/* Material UI overlay utilities */
@utility overlay-* {
  background-image: --value(--overlay-*);
}

/* Material UI elevation utilities */
@utility elevation-* {
  background-image: --value(--overlay-*);
  box-shadow: --value(--shadow-*);
}
```

Then you can start using the new classes—for example:

- The class `typography-h1` produces `font: var(--mui-font-h1);`
- The class `text-primary` produces `color: var(--mui-palette-primary-main);`

So when you add these classes to an element…

```js title="App.tsx"
<div className="typography-h1 text-primary">Hello world</div>
```

…the CSS looks like this:

```css
@layer utilities {
  .typography-h1 {
    font: var(--mui-font-h1);
    letter-spacing: -0.01562em;
  }
  .text-primary {
    color: var(--mui-palette-primary-main);
  }
}
```

### Playground

Visit the [Tailwind CSS Playground](https://play.tailwindcss.com/mh7Ym0mGff) to explore the classes from Material UI theme tokens.

## Troubleshooting

If the Tailwind CSS classes are not overriding Material UI components, make sure that:

- You are using Tailwind CSS >= v4.
- You have configured the layer order correctly by checking the [DevTools styles tab](https://developer.chrome.com/docs/devtools/css/reference#cascade-layers). The `mui` layer should come before the `utilities` layer.
