首页
/ Material UI 样式库互操作完全指南:从 Plain CSS、styled-components 到 Tailwind CSS 的集成实践

Material UI 样式库互操作完全指南:从 Plain CSS、styled-components 到 Tailwind CSS 的集成实践

2026-09-06 14:47:17作者:裘晴惠Vivianne

本篇技术指南基于 Material UI 官方的样式库互操作(Style library interoperability)文档整理而成,系统讲解如何在保留 Material UI 组件能力的同时,接入 Plain CSS、Global CSS、styled-components、CSS Modules、Emotion、Tailwind CSS v3 乃至 TSS 等主流样式方案。读完后,你将掌握每种方案的完整接入步骤、CSS 注入顺序的控制机制(StyledEngineProvider injectFirst、Emotion prepend 缓存等),以及如何通过 slotProps:globalclasses 等 API 精确覆盖 Slider、Tooltip 等组件的深度子元素样式,并可结合仓库源码理解各方案背后的实现原理。

一、互操作的前提:Material UI 的样式引擎抽象

Material UI 默认使用 Emotion 作为样式引擎,所有组件都依赖 styled() API 向页面注入 CSS。由于 styled() 是多个流行样式库共用的 API,Material UI 允许在不同样式引擎之间切换。仓库中通过两个同接口的包实现这一点:

  • @mui/styled-engine:Emotion 的 styled() API 的薄封装,额外提供 <GlobalStyles />csskeyframe 等工具,这是默认方案,无需安装
  • @mui/styled-engine-sc:面向 styled-components 的对应封装,需要显式安装并配置。

从源码结构看,@mui/styled-engine 入口文件 直接重导出了 styledcsskeyframesThemeContextStyledEngineProviderGlobalStyles,并在开发环境下对 styled() 调用做了参数校验(缺少样式参数时会在控制台报错)。两个包实现相同的接口,因此可以互相替换,这也是后文所有互操作示例能够通用的根基。

二、Plain CSS:最基础的互操作

没有任何花哨之处——直接写普通 CSS,通过 className 传给组件即可。

/* PlainCssSlider.css */
.slider {
  color: #20b2aa;
}

.slider:hover {
  color: #2e8b57;
}
/* PlainCssSlider.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
import './PlainCssSlider.css';

export default function PlainCssSlider() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider defaultValue={30} className="slider" />
    </div>
  );
}

CSS 注入顺序 ⚠️

注意:大多数 CSS-in-JS 方案会把样式注入到 HTML <head> 的底部,这会让 Material UI 的样式优先于你的自定义样式生效。如果希望去掉 !important,需要调整 CSS 注入顺序。在 Material UI 中可以通过 StyledEngineProvider 完成:

import * as React from 'react';
import { StyledEngineProvider } from '@mui/material/styles';

export default function GlobalCssPriority() {
  return (
    <StyledEngineProvider injectFirst>
      {/* Your component tree. Now you can override Material UI's styles. */}
    </StyledEngineProvider>
  );
}

注意:如果你使用 Emotion 且在应用中配置了自定义缓存,它会覆盖 Material UI 内置的缓存。为了让注入顺序仍然正确,需要给缓存添加 prepend 选项:

import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';

const cache = createCache({
  key: 'css',
  prepend: true,
});

export default function PlainCssPriority() {
  return (
    <CacheProvider value={cache}>
      {/* Your component tree. Now you can override Material UI's styles. */}
    </CacheProvider>
  );
}

注意:如果你使用 styled-components 并通过 StyleSheetManager 指定了自定义 target,请确保该 target 是 HTML <head> 中的第一个元素。可以参考 @mui/styled-engine-sc 包中 StyledEngineProvider 的实现——它在 injectFirsttrue 时,会创建一个带 data-styled="active" 属性的 <style> 节点并插入到 <head> 的最前面,从而让 styled-components 后续注入的样式紧跟其后,整体位于 Material UI 样式之前。

深度子元素(Deeper elements)

当你尝试给 Slider 定制样式时,往往需要影响它的子元素,例如滑块 thumb。在 Material UI 中,所有子元素都拥有提升后的选择器特异性(specificity 为 2):.parent .child {}。写覆盖样式时必须遵循同样的规则。

下面的示例在自定义 Slider 自身样式的同时,覆盖了 thumb 的样式(依赖 默认生成的 className):

/* PlainCssSliderDeep1.css */
.slider {
  color: #20b2aa;
}

.slider:hover {
  color: #2e8b57;
}

.slider .MuiSlider-thumb {
  border-radius: 1px;
}
/* PlainCssSliderDeep1.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
import './PlainCssSliderDeep1.css';

export default function PlainCssSliderDeep1() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider defaultValue={30} className="slider" />
    </div>
  );
}

此外,你也可以不依赖默认类名,改用 slotProps API 提供自己的类名:

/* PlainCssSliderDeep2.css */
.slider {
  color: #20b2aa;
}

.slider:hover {
  color: #2e8b57;
}

.slider .thumb {
  border-radius: 1px;
}
/* PlainCssSliderDeep2.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
import './PlainCssSliderDeep2.css';

export default function PlainCssSliderDeep2() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider
        defaultValue={30}
        className="slider"
        slotProps={{ thumb: { className: 'thumb' } }}
      />
    </div>
  );
}

三、Global CSS:直接命中 Material UI 生成的类名

显式给每个组件传 className 太麻烦?你可以直接针对 Material UI 生成的全局类名写样式:

/* GlobalCssSlider.css */
.MuiSlider-root {
  color: #20b2aa;
}

.MuiSlider-root:hover {
  color: #2e8b57;
}
/* GlobalCssSlider.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
import './GlobalCssSlider.css';

export default function GlobalCssSlider() {
  return <Slider defaultValue={30} />;
}

CSS 注入顺序 ⚠️

与 Plain CSS 相同:Material UI 的样式默认注入在 <head> 底部、优先于你的全局 CSS。同样使用 StyledEngineProvider injectFirst(Emotion 用户配合 prepend: true 缓存,styled-components 用户配合 StyleSheetManager 的头部 target)调整注入顺序,代码示例与前文 Plain CSS 一节一致,此处不再赘述。

深度子元素

同样需要遵循 .parent .child 的特异性规则。示例在自定义 Slider 样式之外覆盖 thumb:

/* GlobalCssSliderDeep.css */
.MuiSlider-root {
  color: #20b2aa;
}

.MuiSlider-root:hover {
  color: #2e8b57;
}

.MuiSlider-root .MuiSlider-thumb {
  border-radius: 1px;
}
/* GlobalCssSliderDeep.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
import './GlobalCssSliderDeep.css';

export default function GlobalCssSliderDeep() {
  return <Slider defaultValue={30} />;
}

四、styled-components:替换默认样式引擎

更换默认的 styled engine

默认情况下,Material UI 组件以 Emotion 作为样式引擎。如果你希望改用 styled-components,需要按 styled-components 集成指南 配置打包器,把 @mui/styled-engine 替换为 @mui/styled-engine-sc

  • yarn:通过 resolutions 指定 "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest"
  • npm / webpack:在 resolve.alias 中配置 '@mui/styled-engine': '@mui/styled-engine-sc',TypeScript 项目还需在 tsconfig.jsonpaths 中做同样的映射;
  • Next.js:在 next.config.js 中通过 webpack 回调配置别名。

采用这一方案可以减少打包体积,并且不再需要单独配置 CSS 注入顺序。引擎配置完成后,即可使用 @mui/material/styles 导出的 styled() 工具,并直接访问主题(theme)。

import * as React from 'react';
import Slider from '@mui/material/Slider';
import { styled } from '@mui/material/styles';

const CustomizedSlider = styled(Slider)`
  color: #20b2aa;

  :hover {
    color: #2e8b57;
  }
`;

export default function StyledComponents() {
  return <CustomizedSlider defaultValue={30} />;
}

深度子元素

同样地,Material UI 的子元素特异性为 2,覆盖样式需要遵循相同规则。示例覆盖 Slider 的 thumb 样式:

/* 对应仓库示例:docs/data/material/integrations/interoperability/StyledComponentsDeep.js */
import { styled } from '@mui/material/styles';
import Slider from '@mui/material/Slider';

const CustomizedSlider = styled(Slider)`
  color: #20b2aa;

  &:hover {
    color: #2e8b57;
  }

  & .MuiSlider-thumb {
    border-radius: 1px;
  }
`;

上述写法依赖默认生成的 className,你同样可以用 slotProps API 提供自己的类名:

import * as React from 'react';
import { styled } from '@mui/material/styles';
import Slider from '@mui/material/Slider';

const CustomizedSlider = styled((props) => (
  <Slider slotProps={{ thumb: { className: 'thumb' } }} {...props} />
))`
  color: #20b2aa;

  :hover {
    color: #2e8b57;
  }

  & .thumb {
    border-radius: 1px;
  }
`;

export default function StyledComponentsDeep2() {
  return (
    <div>
      <Slider defaultValue={30} />
      <CustomizedSlider defaultValue={30} />
    </div>
  );
}

主题(Theme)

使用 Material UI 的 ThemeProvider 后,主题会同时出现在样式引擎(Emotion 或 styled-components,取决于你的配置)的主题上下文里。

警告:如果你已经在项目中为 styled-components 或 Emotion 使用了自定义主题,它可能不符合 Material UI 的主题规范。若不兼容,需要先渲染 Material UI 的 ThemeProvider,以保证两套主题结构相互隔离。这是渐进式采用 Material UI 组件的理想做法。

官方鼓励在 Material UI 与项目其余部分之间共享同一个主题对象

const CustomizedSlider = styled(Slider)(
  ({ theme }) => `
  color: ${theme.palette.primary.main};

  :hover {
    color: ${darken(theme.palette.primary.main, 0.2)};
  }
`,
);

门户(Portals)

Material UI 的 Portal 组件提供了将子节点渲染到父组件 DOM 层级之外 DOM 节点的一等方式。由于 styled-components 按 CSS 作用域的方式组织样式,对 portal 出来的元素做样式化可能会失效。

例如,当你想定制 Tooltip 生成的提示气泡时,需要把 className 传递到被渲染在 DOM 层级之外的元素上。下面的示例给出了一种解决办法:

import * as React from 'react';
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';

const StyledTooltip = styled(({ className, ...props }) => (
  <Tooltip {...props} classes={{ popper: className }} />
))`
  & .MuiTooltip-tooltip {
    background: navy;
  }
`;

五、CSS Modules

基本用法

/* CssModulesSlider.module.css */
.slider {
  color: #20b2aa;
}

.slider:hover {
  color: #2e8b57;
}
/* CssModulesSlider.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
// webpack, Parcel or else will inject the CSS into the page
import styles from './CssModulesSlider.module.css';

export default function CssModulesSlider() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider defaultValue={30} className={styles.slider} />
    </div>
  );
}

CSS 注入顺序 ⚠️

原理与前文一致:Material UI 样式默认注入在 <head> 底部、优先于 CSS Modules 引入的样式,需要调整注入顺序:

  • 通用做法:<StyledEngineProvider injectFirst>
  • Emotion 自定义缓存:createCache({ key: 'css', prepend: true }) 并通过 CacheProvider 注入;
  • styled-components 的 StyleSheetManager:确保自定义 target<head> 的第一个元素(可参考 styled-engine-sc 的 StyledEngineProvider 实现)。

深度子元素

CSS Modules 会对类名做本地作用域转换,生成类不会匹配 Material UI 的全局类名,因此需要用 :global 选择器来命中 Material UI 的类名。

方式一:使用 :global

/* CssModulesSliderDeep1.module.css */
.slider {
  color: #20b2aa;
}

.slider:hover {
  color: #2e8b57;
}

.slider :global(.MuiSlider-thumb) {
  border-radius: 1px;
}
/* CssModulesSliderDeep1.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
import styles from './CssModulesSliderDeep1.module.css';

export default function CssModulesSliderDeep1() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider defaultValue={30} className={styles.slider} />
    </div>
  );
}

方式二:使用 slotProps

/* CssModulesSliderDeep2.module.css */
.slider {
  color: #20b2aa;
}

.slider:hover {
  color: #2e8b57;
}

.slider .thumb {
  border-radius: 1px;
}
/* CssModulesSliderDeep2.js */
import * as React from 'react';
import Slider from '@mui/material/Slider';
import styles from './CssModulesSliderDeep2.module.css';

export default function CssModulesSliderDeep2() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider
        defaultValue={30}
        className={styles.slider}
        slotProps={{ thumb: { className: styles.thumb } }}
      />
    </div>
  );
}

用 CSS Modules 命中 Material UI 的状态类

Material UI 使用全局类名表示组件状态(例如 .Mui-selected.Mui-disabled)。由于 CSS Modules 的样式是本地作用域的,命中这些全局状态类同样需要 :global

/* MyList.module.css */
.myListItem {
  padding: 10px;
  border-bottom: 1px solid #ccc;
}

/* Combine global state class with a locally scoped class */
:global(.Mui-selected).myListItem {
  background-color: #1976d2;
  color: white;
}
import * as React from 'react';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';
import styles from './MyList.module.css';

export default function MyList() {
  return (
    <List>
      <ListItem className={styles.myListItem} selected>
        <ListItemText primary="Selected item" />
      </ListItem>
      <ListItem className={styles.myListItem}>
        <ListItemText primary="Regular item" />
      </ListItem>
    </List>
  );
}

这个技巧让你在保持模块化样式的同时,响应 Material UI 全局类名所表达的动态状态。

六、Emotion:Material UI 的原生引擎

css prop

Emotion 的 css() 方法与 Material UI 无缝配合,例如 官方示例 EmotionCSS

/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import Slider from '@mui/material/Slider';

export default function EmotionCSS() {
  return (
    <Slider
      defaultValue={30}
      css={css`
        color: #20b2aa;

        :hover {
          color: #2e8b57;
        }
      `}
    />
  );
}

主题与 styled() API

这两者与 styled-components 方案完全一致,直接沿用上一节的说明:共享同一个主题对象、通过 ThemeProvider 隔离不兼容的主题、使用 @mui/material/stylesstyled() 访问 theme 上下文。

七、Tailwind CSS v3 集成

说明:Tailwind CSS v4 的集成方式已有变化(基于 CSS @layer 指令与层序控制),请参考仓库中的 Tailwind CSS v4 集成指南;本节完整覆盖 v3 的做法。

仓库提供了现成的 Vite + TypeScript 示例工程 material-ui-vite-tailwind-ts,可直接作为起点。使用其他框架或已有项目时,按下面 5 个步骤操作:

1. 安装 Tailwind CSS

按 Tailwind CSS 官方安装指南为项目引入 Tailwind(以 Vite 为例,在 vite.config.ts 中挂载 @tailwindcss/vite 插件即可)。

2. 关闭 Tailwind 的 preflight

移除 Tailwind CSS 的 preflight 样式,让 Material UI 的 CssBaseline 取而代之:

 /* tailwind.config.js */
 module.exports = {
+  corePlugins: {
+    preflight: false,
+  },
 };

3. 配置 important 选项(使用应用包裹层的 id)

  • Next.js 项目使用 #__nextNext.js 13+(App Router)注意:Next.js 不再自动添加该 id,需要手动在根元素(通常是 <body>)上添加 id="__next"

    <body id="__next">{/* Your app content */}</body>
    
  • Vite/SPA 项目使用 #root(大多数模板的默认值)。

 /* tailwind.config.js */
 module.exports = {
   content: [
     "./src/**/*.{js,jsx,ts,tsx}",
   ],
+  important: '#__next', // or '#root'
   theme: {
     extend: {},
   },
   plugins: [],
 }

Material UI 使用的大部分 CSS 特异性为 1,因此这个 important 选项通常并非必需。但少数边缘情况下,Material UI 会用到嵌套 CSS 选择器,特异性超过 Tailwind。配置该选项可以确保深度子元素始终能被 Tailwind 工具类覆盖。

4. 修正 CSS 注入顺序

大多数 CSS-in-JS 方案把样式注入到 <head> 底部,导致 Material UI 优先于 Tailwind。为减少 important 属性的使用频率,需要调整注入顺序——通用做法仍是 <StyledEngineProvider injectFirst>;Emotion 自定义缓存用户需加 prepend: true;styled-components 用户需保证 StyleSheetManagertarget 位于 <head> 首位。

5. 更改 Portal 元素的挂载容器

把 Portal 相关元素注入到第 3 步 important 选项所用的应用主包裹层之内:

// For Next.js:
const rootElement = document.getElementById("__next");
// For Vite/SPA:
// const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

const theme = createTheme({
  components: {
    MuiPopover: {
      defaultProps: {
        container: rootElement,
      },
    },
    MuiPopper: {
      defaultProps: {
        container: rootElement,
      },
    },
    MuiDialog: {
      defaultProps: {
        container: rootElement,
      },
    },
    MuiModal: {
      defaultProps: {
        container: rootElement,
      },
    },
  },
});

root.render(
  <StyledEngineProvider injectFirst>
    <ThemeProvider theme={theme}>
      <App />
    </ThemeProvider>
  </StyledEngineProvider>,
);

故障排查

如果样式没有正确生效,依次检查:

  1. 根元素 id 是否与 Tailwind 配置中的 important 选择器一致
框架 根元素 ID important 选择器
Next.js id="__next" #__next
Vite/SPA id="root" #root
  1. 确认已设置 preflight: false
  2. 确认 StyledEngineProviderinjectFirst 已正确配置。

开始使用

配置完成后即可在 Material UI 组件上直接使用 Tailwind 工具类:

/* index.tsx */
import * as React from 'react';
import Slider from '@mui/material/Slider';

export default function App() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider defaultValue={30} className="text-teal-600" />
    </div>
  );
}

深度子元素

定制 Slider 时通常也要覆盖子元素,例如 thumb。利用 slotProps 把工具类传到子元素上:

/* SliderThumbOverrides.tsx */
import * as React from 'react';
import Slider from '@mui/material/Slider';

export default function SliderThumbOverrides() {
  return (
    <div>
      <Slider defaultValue={30} />
      <Slider
        defaultValue={30}
        className="text-teal-600"
        slotProps={{ thumb: { className: 'rounded-sm' } }}
      />
    </div>
  );
}

伪状态(pseudo states)

若要针对组件的伪状态定制样式,可以使用 classes prop 中对应的键。例如定制 Slider 的 active 状态:

/* SliderPseudoStateOverrides.tsx */
import * as React from 'react';
import Slider from '@mui/material/Slider';

export default function SliderThumbOverrides() {
  return <Slider defaultValue={30} classes={{ active: 'shadow-none' }} />;
}

八、从 JSS 迁移到 TSS

JSS 本身已不再被 Material UI 支持。但如果你喜欢 JSS 时代基于 hook 的 API(makeStylesuseStyles),可以选择 tss-react 这类替代方案——它与 Material UI 集成良好,且提供比 JSS 更好的 TypeScript 支持。

@material-ui/core(v4)升级到 @mui/material(v5)的项目,可参考迁移指南中的 tss-react 章节。

基本挂载方式:为 tss-react 与 Material UI 分别创建 Emotion 缓存,并不要再使用 <StyledEngineProvider injectFirst />

import { render } from 'react-dom';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import { ThemeProvider } from '@mui/material/styles';

export const muiCache = createCache({
  key: 'mui',
  prepend: true,
});

//NOTE: Don't use <StyledEngineProvider injectFirst/>
render(
  <CacheProvider value={muiCache}>
    <ThemeProvider theme={myTheme}>
      <Root />
    </ThemeProvider>
  </CacheProvider>,
  document.getElementById('root'),
);

之后直接 import { makeStyles, withStyles } from 'tss-react/mui' 即可。传给回调函数的主题对象就是 import { useTheme } from '@mui/material/styles' 获取到的主题。如果想完全控制传给 makeStyles/withStylestheme 对象,可以从一个文件(例如 makesStyles.ts)重新导出它们:

import { useTheme } from '@mui/material/styles';
//WARNING: tss-react require TypeScript v4.4 or newer. If you can't update use:
//import { createMakeAndWithStyles } from "tss-react/compat";
import { createMakeAndWithStyles } from 'tss-react';

export const { makeStyles, withStyles } = createMakeAndWithStyles({
  useTheme,
  /*
    OR, if you have extended the default mui theme adding your own custom properties:
    Let's assume the myTheme object that you provide to the <ThemeProvider /> is of
    type MyTheme then you'll write:
    */
  //"useTheme": useTheme as (()=> MyTheme)
});

使用方式:

import { makeStyles } from 'tss-react/mui';

export function MyComponent(props: Props) {
  const { className } = props;

  const [color, setColor] = useState<'red' | 'blue'>('red');

  const { classes, cx } = useStyles({ color });

  //Thanks to cx, className will take priority over classes.root
  return <span className={cx(classes.root, className)}>hello world</span>;
}

const useStyles = makeStyles<{ color: 'red' | 'blue' }>()((theme, { color }) => ({
  root: {
    color,
    '&:hover': {
      backgroundColor: theme.palette.primary.main,
    },
  },
}));

SSR 等进阶用法请参考 TSS 官方文档;它还提供检测未使用类名的 ESLint 插件。

警告:请保留 @emotion/styled 作为项目的依赖,即使你从未显式使用它——它是 @mui/material 的 peer dependency。

九、源码视角:CSS 注入顺序的控制机制

前面各节反复出现的「调整 CSS 注入顺序」,其底层实现正是两个 styled engine 包中的 StyledEngineProvider

Emotion 版实现

StyledEngineProvider(Emotion 版) 的源码可以看出其工作机制:

  1. 创建插入点:模块加载时(浏览器环境),先在 <head> 最前面插入一个 <meta name="emotion-insertion-point"> 节点(L57-L71);
  2. injectFirst 生效:当传入 injectFirst 时,getCache() 会创建一个自定义 Emotion 缓存,把 insertionPoint 指向上述 meta 节点,使 Material UI 的样式被注入到 <head> 前端,从而让后加载的外部样式表(Plain CSS / CSS Modules / Tailwind)拥有更高优先级(L73-L116);
  3. enableCssLayer 进阶:该 prop 会把 Material UI 的样式整体包裹进 @layer mui,为 Tailwind v4 等基于层序(layer order)的方案服务;层缓存使用独立 key mui,避免与未分层的 css 缓存产生类名哈希冲突。

测试用例 StyledEngineProvider.test.tsx 验证了这些行为:enableCssLayer 下生成的规则确实是 @layer mui{html{color:red;}},且同一 injectFirst 配置在组件树多层嵌套时会复用同一个缓存实例。

styled-components 版实现

StyledEngineProvider(styled-engine-sc 版) 的逻辑更简单:injectFirsttrue 时,在 <head> 首位插入一个空的 <style data-styled="active"> 节点,styled-components 会把后续样式紧跟该节点注入,从而整体排到 Material UI 样式之前。这也解释了文档中「确保 StyleSheetManager 的自定义 target<head> 第一个元素」这一要求的由来。

三种调整注入顺序的方案对比

方案 做法 关键点
Material UI 内置 <StyledEngineProvider injectFirst> Emotion 版经 meta 插入点、styled-engine-sc 版经 data-styled="active" 节点实现
Emotion 自定义缓存 createCache({ key: 'css', prepend: true }) + CacheProvider 自定义缓存会覆盖 Material UI 默认缓存,必须手动加 prepend
styled-components StyleSheetManager 的自定义 target target 必须是 <head> 第一个元素

十、小结

Material UI 的样式库互操作建立在三块基石之上:可替换的 styled() 引擎接口(@mui/styled-engine / @mui/styled-engine-sc)、可控的 CSS 注入顺序(injectFirst / prepend / 头部 target),以及面向深度子元素的稳定覆盖手段(默认 MuiXxx 类名、slotPropsclasses 伪状态键、CSS Modules 的 :global)。按照本文步骤,你可以在不牺牲 Material UI 组件能力的前提下,把现有项目的任意主流样式方案与 Material UI 平滑组合,并能借助 packages/mui-styled-enginepackages/mui-styled-engine-sc 两个包的源码验证每一步配置的实际效果。

登录后查看全文
热门项目推荐
相关项目推荐