0%

【React UI 庫比較 - 2】MUI 主題客製化 + Tailwind 協作

上篇介紹 MUI 基本安裝與使用方法,但我們不太可能用 MUI 完成整個網站的切版對吧?所以此篇將聚焦:

  • MUI 與 Tailwind 協作
  • 元件與主題客製化
    這篇文章會更貼近實務應用情境作介紹

Theme Cover

在 MUI 元件使用 Tailwind CSS v4

MUI 元件設定客製化有兩種方式

  • 透過 sx 傳入 props,<Box sx={{ width: 1024 }}>這是容器</Box>

  • 透過 Tailwind 設定,如果你是 Vite,可參考此篇官方文章。GlobalStyles styles 注入的樣式順序請按照官方文章指示,Tailwind 會使用 utilties layer 注入,如果 utilies 在 mui layer 前面會無法蓋過。
    設定完畢後,就可以在 MUI component 使用 <Box className="w-[1024px]">這是容器</Box>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 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>,
    );

    CSS Layer

讓 Tailwind 也能使用 MUI 樣式

  1. 官方文件上的程式碼貼到你的全域 CSS 上,視每個專案結構,貼在 index.css 或創立新的 css 檔案都可以。

  2. 使用 createTheme 將 MUI 原生的主題套用進全域設定,className 也可以使用 MUI 設定了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import './index.css'
    import { StyledEngineProvider, ThemeProvider, createTheme } from '@mui/material/styles'
    import GlobalStyles from '@mui/material/GlobalStyles'

    // 使用預設主題並啟用 CSS 變數
    const defaultTheme = createTheme({
    cssVariables: true, // 關鍵設定,讓 index.css 的 MUI 變數生效
    })

    createRoot(document.getElementById('root')!).render(
    <StrictMode>
    <StyledEngineProvider enableCssLayer>
    <ThemeProvider theme={defaultTheme}>
    <GlobalStyles styles="@layer theme, base, mui, components, utilities;" />
    <App />
    </ThemeProvider>
    </StyledEngineProvider>
    </StrictMode>
    )

    image

客製 MUI 主題

通常網站都會有自己的一套 Design Guideline

如果你是設計師

  • 推薦你下載 MUI 社群發表的 Figma UI Kit,幫助,在既有基礎上修改樣式,保留更多時間設計與組裝畫面。
  • 也可以使用 MUI 提供的主題編輯器預覽你的色彩設定,加速溝通。
    MUI Theme Creator

如果你是工程師

我們可以使用 createTheme 覆蓋或擴充 MUI 原生樣式。

  1. 建立一個 muiTheme 檔案和資料夾,如果你是用的是 TypeScript 並且想擴充色票,這個資料夾還需要多新增一個 theme.d.ts。
    image

  2. 如果只是要覆蓋原生色票是使用 palette,覆蓋字級則是 typography

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // muiTheme.tsx
    import { createTheme } from '@mui/material/styles';

    // MUI 主題配置
    export const muiTheme = createTheme({
    cssVariables: true, // 啟用 CSS 變數
    palette: {
    primary: {
    main: '#2e7d32', // 綠色
    },
    },
    typography: {
    fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
    h1: {
    fontSize: '1rem',
    fontWeight: 300,
    }
    }
    })

    export default muiTheme

    將客製主題使用 ThemeProvider 注入在全域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // main.tsx
    import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles'
    import GlobalStyles from '@mui/material/GlobalStyles';
    import { muiTheme } from './muiTheme/muiTheme'

    createRoot(document.getElementById('root')!).render(
    <StrictMode>
    <StyledEngineProvider enableCssLayer>
    <ThemeProvider theme={muiTheme}>
    <GlobalStyles styles="@layer theme, base, mui, components, utilities;" />
    <App />
    </ThemeProvider>
    </StyledEngineProvider>
    </StrictMode>
    )
  3. 自訂色票可以分為自訂「自訂色票」和「既有色票的輔助色」兩種辦法

    • 既有色票輔助色:
      PrimarySecondary 是既有色票,原生的輔助色有 mainlightdark 等。假設我們今天想新增輔助色 extraDark
      // muiTheme.tsx const theme = createTheme({ colorSchemes: { light: { palette: { primary: { main: '#2e7d32', // 覆蓋色票 extraDark: "#541437", // 新增色票 }, }, } }, }); export default theme;
    • 自訂色票:
      新增 PrimarySecondary 以外名稱的色票,假設名稱為 background.default
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      // muiTheme.tsx
      const theme = createTheme({
      colorSchemes: {
      light: {
      palette: {
      background: {
      extraLight: "#F7F7F7",
      },
      },
      }
      },
      });
      export default theme;
      不管是擴充輔助色或是色票,如果有設定同步給 Tailwind 使用,別忘了要回到 CSS 檔案手動擴充呦!
      設定擴充 tailwind
  4. 直接客製主題中的元件樣式
    依照文件中的示範,createTheme 中可以直接設定元件樣式。以下面設定 Button 樣式說明,我們可以看到像是&.Mui-disabled的樣式,這些樣式來源可以透過每個元件頁面,最下面的 API 文件中 CSS classes 段落找到。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    const theme = createTheme({
    components: {
    MuiButton: {
    styleOverrides: {
    root: ({ theme }) => ({
    '&.Mui-disabled': {
    color: theme.palette.text.disabled,
    },
    }),
    contained: ({ theme }) => ({
    '&.MuiButton-containedPrimary:hover': {
    backgroundColor: theme.palette.primary.dark,
    },
    }),
    outlined: ({ theme }) => ({
    '&.MuiButton-outlinedPrimary:hover': {
    backgroundColor: theme.palette.primary.dark,
    },
    }),
    },
    },
    },
    });

擴充色票需要額外設定 TypeScript 型別

如果使用 TypeScript,我們需要用上剛才新建的 theme.d.ts 檔案定義型別來避免報錯。更多設定請參考文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// theme.d.ts
import {} from "@mui/material";

declare module "@mui/material/styles" {
// 擴充 MUI Palette 中的輔助色
interface PaletteColor {
extraLight?: string;
extraDark?: string;
}
// 擴充 createTheme MUI Palette 中的輔助色
interface SimplePaletteColorOptions {
extraLight?: string;
extraDark?: string;
}
// 建立新 Palette
interface TypeBackground {
extraLight?: string;
}
}