[TOC]
客製化樣式的方法
原則
建議的順序:
- 使用
classNames或className:搭配 CSS Modules 或 TailwindCSS 的 utility classes - 修改 CSS 變數
- 使用
style或styles
客製化全域樣式
建議的順序:
- 使用 createTheme 來修改全域的主題
- 使用 CSS variables resolver 來修改全域的環境變數
客製化全域元件
[!tip]
看到「顏色」要想到支援 light 和 dark theme(color variant 則不需要考慮);看到「尺寸」要想到要支援不同的 size variant。
建議的順序:
- 如果顏色的改變是透過元件上的 color 屬性,例如
<Badge color="indigo" />則建議透過variantColorResolver來修改顏色,原因是當元件使用了color它就不應該因為 theme 而有不同顏色 - 在
createTheme中使用classNames來覆蓋元件的樣式,可以使用 TailwindCSS 的 utility classes 或 CSS Modules 搭配 CSS variables- 適合用在和「顏色」有關的變更,因為可以同時支援深色主題(例外,顏色的改變是透過元件上的 color 屬性,應該要使用
variantColorResolver) - 不適合用在「尺寸」有關的變更,因為尺寸相關的設定常會跟著 variant(例如,
size)而有不同
- 適合用在和「顏色」有關的變更,因為可以同時支援深色主題(例外,顏色的改變是透過元件上的 color 屬性,應該要使用
- 在
createTheme中使用var來覆蓋元件的「CSS variables」:- 適合用在和「尺寸」、「大小」有關的設定
- 不適合用在改變顏色(因為不方便同時支援深色和暗色主題),適合用在需要使用自訂的 theme,或想覆蓋元件的 CSS variables
- Button 的 height 或 width 不要訂成 var,但 spacing 和 designer 確認後可能可以
- 在
createTheme中使用styles來覆蓋元件的樣式
// 在 Mantine 中是透過 createTheme 來產生對應的 CSS Variables
const themeOverride = createTheme({
components: {
Select: Select.extend({
// 使用 classNames 的方式覆蓋掉原本 Mantine 定義的樣式
classNames: {
input: 'dark:bg-slate-700 dark:border-slate-600',
},
// 使用 vars 修改 components 內 css variables
// 注意:這個做法的問題會是沒辦法同時支援 light/dark 主題
// Mantine 的做法是會在 component 上多出 inline styles 來做 css variable 的覆寫
vars: (theme, props) => {
return {
input: {
'--input-bg': theme.colors.dark[7],
'--input-bd': theme.colors.dark[6],
},
};
},
}),
},
});
客製化區域元件
建議的順序:
- 直接使用
className或classNames覆蓋元件的樣式:搭配 CSS Modules 或 TailwindCSS 的 utility classes - 使用 Style Props 覆蓋元件的樣式
- 使用
styles覆蓋元件的樣式 - 使用
style覆蓋元件的樣式
Q & A
共用相同的 Popover 元素
在 Mantine 中, Popover、Select 這類元件都有用到 dropdown ,而這個 dropdown 實際上會被共用。具體來說,假設我想要分別針對 Popover 和 Select 中的 Dropdown 進行客製化調整,可能會這樣寫:
// ‼️ 這是有問題的寫法
import { createTheme, Popover, Select } from '@mantine/core';
export const theme = createTheme({
components: {
Select: Select.extend({
classNames: {
dropdown: 'dark:bg-purple-700',
},
}),
Popover: Popover.extend({
classNames: {
dropdown: 'dark:bg-sky-800',
},
}),
},
});
並且預期 Select 底下的 dropdown 會是紫色、 Popover 底下的 dropdown 則是藍色。然而,實際上的結果並不是這樣,而是全都變成了藍色:

從最終生成的 HTML 可以看到,實際上:
- Select 裡的 dropdown 會同時套用
dark:bg-sky-800、dark:bg-purple-700、mantine-Popover-dropdown和mantine-Select-dropdown - Popover 裡的 dropdown 則會套用
dark:bg-sky-800和mantine-Popover-dropdown
也就是說,Select 裡的 dropdown 同時會套用到 Select Dropdown 和 Popover Dropdown 的樣式,進而導致衝突。
要解決這個問題的其中一個方式是透過 CSS Modules 來提升 Select Dropdown 的權重,例如:
// mantine.module.css
// 或者使用 TailwindCSS 提供的 @apply
// @reference "tailwindcss";
.select-dropdown {
// 這裡用 && 來讓 select 中 dropdown 的權重大於 popover 中的 dropdown
&& {
background-color: var(--color-purple-700);
// 或者 @apply bg-purple-700;
}
}
.popover-dropdown {
background-color: var(--color-sky-800);
// 或者 @apply bg-sky-800;
}
// mantine.ts
import { createTheme, Popover, Select } from '@mantine/core';
import classes from './mantine.module.css';
export const theme = createTheme({
components: {
Select: Select.extend({
classNames: {
dropdown: classes.selectDropdown,
},
}),
Popover: Popover.extend({
classNames: {
dropdown: classes.popoverDropdown,
},
}),
},
});
如此才能符合我們預期的將結果呈現出來:

Mantine 搭配 Tailwind CSS 使用
概念
- Mantine 是用 Theme 來產生 CSS Variables,然後再套用到 Components 中使用;TailwindCSS 則是
原則
- 如果是 Mantine 中的 Style Props 一律建議都用 TailwindCSS 提供的 utility classes
- 如果是 component 特定的 props,例如
size這類這可以 rely on Mantine 內建的 theme classNames中能用 TailwindCSS 的 utility classes 就盡可能用
搭配 TailwindCSS 的正確做法
- 要在
index.html中透過<link rel="stylesheet" href="./src/index.css">載入,不可以在index.tsx中透過import './src/index.css'載入- 重點是要確保在
index.css中定義的 layer 順序比'@mantine/core/styles.layer.css'早被載入,如果能確保這點,也不一定要寫在index.html中
- 重點是要確保在
- 在
index.css中定義載入 layers 的順序
// index.css
/**
* Mantine with Tailwind CSS
* 這個 layer 的宣告順序很重要,mantine 必須在 base 之後,components 之前被載入
*/
@layer theme, base, mantine, components, utilities;
/**
* Mantine with Tailwind CSS
* 這個 import 的順序很重要,@layer 一定要確保在最一開始就被載入
*/
@import './config/tailwind.css';
// config/tailwind.css
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/preflight.css' layer(base);
@import 'tailwindcss/utilities.css' layer(utilities);
/**
* Mantine with Tailwind CSS
* Dark Mode: 讓 Tailwind CSS 能夠根據 mantine dark theme 使用的 data-attribute 來切換主題配色
*/
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *, [data-mantine-color-scheme=dark], , [data-mantine-color-scheme=dark] *));
- 檢查載入 layer 的順序如預期:越後面載入的(數字越大的)權重越高

Theme Token 對照
--mantine-scale: 1;
.button {
--button-height-xs: calc(1.875rem * var(--mantine-scale)); /* 30px */
--button-height-sm: calc(2.25rem * var(--mantine-scale)); /* 36px */
--button-height-md: calc(2.625rem * var(--mantine-scale)); /* 42px */
--button-height-lg: calc(3.125rem * var(--mantine-scale)); /* 50px */
--button-height-xl: calc(3.75rem * var(--mantine-scale)); /* 60px */
--button-height-compact-xs: calc(1.375rem * var(--mantine-scale)); /* 22px */
--button-height-compact-sm: calc(1.625rem * var(--mantine-scale)); /* 26px */
--button-height-compact-md: calc(1.875rem * var(--mantine-scale)); /* 30px */
--button-height-compact-lg: calc(2.125rem * var(--mantine-scale)); /* 34px */
--button-height-compact-xl: calc(2.5rem * var(--mantine-scale)); /* 40px */
--button-padding-x-xs: calc(0.875rem * var(--mantine-scale)); /* 14px */
--button-padding-x-sm: calc(1.125rem * var(--mantine-scale)); /* 18px */
--button-padding-x-md: calc(1.375rem * var(--mantine-scale)); /* 22px */
--button-padding-x-lg: calc(1.625rem * var(--mantine-scale)); /* 26px */
--button-padding-x-xl: calc(2rem * var(--mantine-scale)); /* 32px */
--button-padding-x-compact-xs: calc(0.4375rem * var(--mantine-scale)); /* 7px */
--button-padding-x-compact-sm: calc(0.5rem * var(--mantine-scale)); /* 8px */
--button-padding-x-compact-md: calc(0.625rem * var(--mantine-scale)); /* 10px */
--button-padding-x-compact-lg: calc(0.75rem * var(--mantine-scale)); /* 12px */
--button-padding-x-compact-xl: calc(0.875rem * var(--mantine-scale)); /* 14px */
}
官方文件索引
- Styles overview:基本說明各種客製元件的方式
- Mantine styles:說明如何載入 Mantine 的 CSS 檔案
- CSS files list:如果要分別載入不同的 CSS 檔可以看
- CSS modules:如何使用 CSS modules 或 TailwindCSS 來調整元件樣式
- PostCSS preset: mantine 提供的 CSS functions 或 mixin,例如
light-dark() - Global styles:
- CSS Variables:說明有哪些主要的 CSS 變數、如何使用和調整 CSS 變數
- CSS Variables list:快速檢視所有 CSS 變數和值
- style prop:不建議使用
- Styles API
Color
Mantine 預設的 color theme 是來自 open-color 的配色。
Styling
客製化樣式
- Responsive styles:
breakpoint - CSS variables:
spacing- MantineProvider 會根據提供的 theme 來產生對應的 CSS variables。
Styles overview:說明如何客製化樣式
在 Mantine 中,如果要客製化 component 的樣式,建議的方式是:
- 使用 component specific props
- [不建議] 使用 mantine 提供的
style或styles,如果你發現你使用超過 3-4 以上的 style props,建議拆成獨立的樣式檔 - 建議使用 CSS modules 來客製化元件樣式,Mantine 的元件提供
className"s"props 可以帶入樣式 - 雖然建議用 CSS modules,但也可以使用 Tailwind CSS 這類 utility classes 來把樣式透過
className,classNames,style,styles帶入。但要留意使用上可能會遇到限制,例如,使用classNames帶入樣式時,它並不是真的套用這個 CSS Class,而是把值拿出來後,放進全域樣式中,因此最推薦的仍然是使用 CSS Modules。 - 「不建議」使用
style或styles來客製化樣式,建議拆成獨立的樣式 檔
Mantine styles:載入 mantine CSS 檔案的正確方式
使用 mantine 提供的 @layer 方式來載入 CSS 檔就可以避免 CSS 檔案需要按照順序來載入的問題。
其他頁面
CSS files list:mantine 提供的 CSS 檔案列表
variantColorResolver
Variants and sizes @ Styling
在 Mantine 中,有些元件如 Button 、 Badge 、 ActionIcon 等有支援 variantColorResolver 可以客製化 variant 的顏色。
variantColorResolver 會回傳:
export interface VariantColorResolverResult {
background: string; // 元件的背景色
color: string; // 元件的文字顏色
hover: string; // 滑鼠移上去後元件的背景色
hoverColor?: string; // 滑鼠移上去後元件的文字顏色
border: string;
}
舉例來說:
import { alpha } from '@mantine/core';
const variantColorResolver: VariantColorsResolver = (input) => {
const defaultResolvedColors = defaultVariantColorsResolver(input);
const parsedColor = parseThemeColor({
color: input.color || input.theme.primaryColor,
theme: input.theme,
});
// Override some properties for variant
if (parsedColor.isThemeColor && parsedColor.color === 'indigo' && input.variant === 'filled') {
return {
...defaultResolvedColors,
// 可以使用 Mantine 提供的 alpha 來改變透明度
background: alpha('var(--color-indigo-700)', 0.8),
color: alpha('var(--color-gray-300)', 0.9),
hover: alpha('var(--color-red-600)', 0.8),
border: alpha('var(--color-red-600)', 0.8),
hoverColor: 'yellow',
};
}
return defaultResolvedColors;
};
其他筆記
CSS Layer
- 沒有放在
@layer裡的樣式會比有放在裡面的權重來得高 - 如果樣式都用放在
@layer裡,權重會受到以下的影響:- 有在最上方定義不同 layer 的權重順序,例如
@layer base, components, utilities,則會遵守這裡定義的權重順序,越後面的權重越高 - 如果沒有在最上方定義權重順序,則越晚載入的
@layer權重越高
- 有在最上方定義不同 layer 的權重順序,例如
其他可以參考的套件
- react-number-format:mantine 後面用來處理 number 呈現的工具
- https://github.com/icflorescu/mantine-contextmenu:使用者點擊右鍵後可以出現的選單
- https://github.com/icflorescu/mantine-datatable
- https://github.com/KevinVandy/mantine-react-table/tree/v2:參考程式碼就好,因為沒有更新,跟不上最新的 mantine 和 tanstack table,所以不建議使用