Skip to content
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

[material-ui] Opt-in support for @layer to fix Tailwind v4 integration #44700

Open
siriwatknp opened this issue Dec 9, 2024 · 5 comments
Open
Assignees
Labels
package: material-ui Specific to @mui/material RFC Request For Comments

Comments

@siriwatknp
Copy link
Member

siriwatknp commented Dec 9, 2024

Demo

Repo: https://github.com/siriwatknp/mui6-tailwind4-vite
Preview: https://siriwatknp.github.io/mui6-tailwind4-vite/

Motivation

Tailwind integration

The current Material UI v6 is hard to use with CSS utilities like Tailwind CSS because some components have higher CSS specificity than (0,1,0) so Tailwind CSS could not be used without !important.

Also, Tailwind v4 (will be stable soon) is using native CSS layer so Material UI won't be able to override it without a configurable layer.

Here is the issue using Material UI v6 + Tailwind v4 (beta). The text-2xl cannot override the Typography base styles.

image

✅ Can be fixed by the first solution

Different override behavior when using CSS variables

Another issue is the behavior change when transition from dynamic CSS using theme.palette.mode to CSS variables paradigm (static CSS). The sx prop cannot override the :where() because Emotion always append :where() at the end of the styles.

✅ Can be fixed by combining first and second solution

Requirements

  • Opt-in solution
  • Least breaking changes
  • Small change for the codebase

Options

1. A custom stylis plugin for single layer

Based on this solution, this will capture emotion styles into a single layer, likely named @layer mui.

I think this is a simplest solution that works really well. It will fix the Tailwind v4 integration but it won't fix the "Different override behavior when using CSS variables" because all Material UI styles are in the same layer.

2. Add flag to the theme for multiple layers

To solve "Different override behavior when using CSS variables", the sx styles must be in a different layer so that it overrides the styles of the component regardless of selector's specificity.

@layer mui, sx

@layer sx {
  .button {
    color: blue; // this wins
  }
}

@layer mui {
  .button {
    color: red;
  };
  :where(.dark) .button {
    color: white;
  }
}

A custom stylis plugin (option 1) is not possible to support multiple layers, so the layer has to be created from the styleFunctionSx.

diff --git a/packages/mui-system/src/styleFunctionSx/styleFunctionSx.js b/packages/mui-system/src/styleFunctionSx/styleFunctionSx.js
index a74b44b553..08362c997f 100644
--- a/packages/mui-system/src/styleFunctionSx/styleFunctionSx.js
+++ b/packages/mui-system/src/styleFunctionSx/styleFunctionSx.js
@@ -131,7 +131,11 @@ export function unstable_createStyleFunctionSx() {
       return sortContainerQueries(theme, removeUnusedBreakpoints(breakpointsKeys, css));
     }
 
-    return Array.isArray(sx) ? sx.map(traverse) : traverse(sx);
+    const array = Array.isArray(sx) ? sx : [sx];
+    return array.map((item) => {
+      const result = traverse(item);
+      return theme.cssLayer ? { [`@layer sx`]: result } : result;
+    });
   }
 
   return styleFunctionSx;

Feel free to share other possible options that we could do.

Search keywords:

@siriwatknp siriwatknp added the RFC Request For Comments label Dec 9, 2024
@siriwatknp siriwatknp mentioned this issue Dec 9, 2024
1 task
@siriwatknp siriwatknp added this to the Material UI v7 (draft) milestone Dec 12, 2024
@DiegoAndai
Copy link
Member

I agree with this to fix the integration with Tailwind v4, keeping in mind the requirements:

  • Opt-in solution
  • Least breaking changes
  • Small change for the codebase

@DiegoAndai DiegoAndai changed the title [RFC] Support @layer [RFC] Opt-in support for @layer to fix Tailwind v4 integration Dec 12, 2024
@DiegoAndai DiegoAndai moved this to Backlog in Material UI Jan 22, 2025
@DiegoAndai DiegoAndai changed the title [RFC] Opt-in support for @layer to fix Tailwind v4 integration [material-ui] Opt-in support for @layer to fix Tailwind v4 integration Jan 23, 2025
@DiegoAndai DiegoAndai added the package: material-ui Specific to @mui/material label Jan 23, 2025
@DiegoAndai DiegoAndai marked this as a duplicate of #45096 Jan 23, 2025
@DiegoAndai DiegoAndai marked this as a duplicate of #45102 Jan 24, 2025
@Malivuca
Copy link

I don't know if this is 100% related to the topic of the issue, but I was having some issues when using Tailwindcss v4, mui v6.4.1 and vite as a bundler, and came up with a simple solution.
I think this can save people a lot of time, because even though you create a brand new react-ts vite template project, follow all the steps listed in the tailwindcss v4 installation guide for vite and the mui style library interoperability docs, mui does not work with the new tailwind version at all.
After some time doing some research, I found that the solution is: go to the main .css file where you import tailwind styles and add a important keyword at the end. Example:

/* index.css */
@import "tailwindcss" important; /* <==== just add the important keyword */

/* other project styles */

Although simple, it is not the same as the previous important: "#root" solution which was used for tailwind v3, since now EVERY tailwindcss has a important flag attached to it, and it might conflict with some mui styles.
Maybe this information should go to the interoperability docs while the layer fix is not implemented yet?

@mrdjohnson
Copy link

I don't know if this is 100% related to the topic of the issue, but I was having some issues when using Tailwindcss v4, mui v6.4.1 and vite as a bundler, and came up with a simple solution. I think this can save people a lot of time, because even though you create a brand new react-ts vite template project, follow all the steps listed in the tailwindcss v4 installation guide for vite and the mui style library interoperability docs, mui does not work with the new tailwind version at all. After some time doing some research, I found that the solution is: go to the main .css file where you import tailwind styles and add a important keyword at the end. Example:

/* index.css /
@import "tailwindcss" important; /
<==== just add the important keyword */

/* other project styles */
Although simple, it is not the same as the previous important: "#root" solution which was used for tailwind v3, since now EVERY tailwindcss has a important flag attached to it, and it might conflict with some mui styles. Maybe this information should go to the interoperability docs while the layer fix is not implemented yet?

@import "tailwindcss" important; worked for me as well thank you. I'm not sure what the drawbacks are but this was a huge timesaver

@HasanMothaffar
Copy link

HasanMothaffar commented Jan 28, 2025

I don't know if this is 100% related to the topic of the issue, but I was having some issues when using Tailwindcss v4, mui v6.4.1 and vite as a bundler, and came up with a simple solution. I think this can save people a lot of time, because even though you create a brand new react-ts vite template project, follow all the steps listed in the tailwindcss v4 installation guide for vite and the mui style library interoperability docs, mui does not work with the new tailwind version at all. After some time doing some research, I found that the solution is: go to the main .css file where you import tailwind styles and add a important keyword at the end. Example:

/* index.css /
@import "tailwindcss" important; /
<==== just add the important keyword */

/* other project styles */

Although simple, it is not the same as the previous important: "#root" solution which was used for tailwind v3, since now EVERY tailwindcss has a important flag attached to it, and it might conflict with some mui styles. Maybe this information should go to the interoperability docs while the layer fix is not implemented yet?

Nice! Thanks for the fix. I knew there was some way to mark layer as important, but couldn't find it on MDN somehow.

You don't have to import all of tailwindcss parts. Based on the instructions here (https://tailwindcss.com/docs/preflight), I'm doing this:

@layer theme, utilities;

@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities) important;

I just put important to the utilities layer. This seems to fix the problem. (I'm using MUI's base css styles, not tailwind's preflight)

@siriwatknp
Copy link
Member Author

@HasanMothaffar @mrdjohnson @Malivuca Please see this repo for proper configuration.

Repo: https://github.com/siriwatknp/mui6-tailwind4-vite
Demo: https://siriwatknp.github.io/mui6-tailwind4-vite/

Summary: set up CSS layer for Material UI to be @components to work with Tailwind CSS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: material-ui Specific to @mui/material RFC Request For Comments
Projects
Status: Backlog
Development

No branches or pull requests

5 participants