--- order: 7 title: Customize Theme --- Ant Design allows you to customize our design tokens to satisfy UI diversity from business or brand requirements, including primary color, border radius, border color, etc. In version 5.0, we provide a new way to customize themes. Different from the less and CSS variables of the 4.x version, with CSS-in-JS, the ability of theming has also been enhanced, including but not limited to: 1. Switching theme dynamically; 2. Multiple themes; 3. Customizing theme variables for some component; 4. ... ## Customize theme with `ConfigProvider` In version 5.0 we call the smallest element that affects the theme **Design Token**. By modifying the Design Token, we can present various themes or components. ### Customize Design Token You can pass `theme` to ConfigProvider to customize theme. After migrate to V5, theme of V5 will be applied by default. Here's a simple example: ```tsx import { Button, ConfigProvider } from 'antd'; import React from 'react'; const App: React.FC = () => ( ; }; export default App; ``` ### Static consume (e.g. less) When you need token out of React life cycle, you can use static function to get them: ```jsx import { theme } from 'antd'; const { defaultAlgorithm, defaultSeed } = theme; const mapToken = defaultAlgorithm(defaultSeed); ``` If you want to use in preprocess style framework like less, use less-loader for injection: ```jsx { loader: "less-loader", options: { lessOptions: { modifyVars: mapToken, }, }, } ``` Compatible package provide convert function to transform to v4 less variable. Read [this](/docs/react/migration-v5) for detail. ## Advanced In Design Token, we provide a three-layer structure that is more suitable for the design, and disassemble the Design Token into three parts: Seed Token, Map Token and Alias Token. These three groups of Tokens are not simple groupings, but a three-layer derivation relationship. Map Tokens are derived from Seed Tokens, and Alias Tokens are derived from Map Tokens. In most cases, using Seed Tokens is sufficient for custom themes. But if you need a higher degree of theme customization, you need to understand the life cycle of Design Token in antd. ### Life Cycle of Design Token ![token](https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*uF3kTrY4InUAAAAAAAAAAAAAARQnAQ) ### Seed Token Seed Token means the origin of all design intent. For example, we can change the theme color by changing `colorPrimary`, and the algorithm inside antd will automatically calculate and apply a series of corresponding colors according to the Seed Token: ```tsx const theme = { token: { colorPrimary: '#1890ff', }, }; ``` ### Map Token Map Token is a gradient variable derived from Seed. It is recommended to implement custom Map Token through `theme.algorithm`, which can ensure the gradient relationship between Map Tokens. It can also be overridden by `theme.token` to modify the value of some map tokens individually. ```tsx const theme = { token: { colorPrimaryBg: '#e6f7ff', }, }; ``` ### Alias Token Alias Token is used to control the style of some common components in batches, which is basically a Map Token alias, or a specially processed Map Token. ```tsx const theme = { token: { colorLink: '#1890ff', }, }; ``` ### Algorithm The basic algorithm is used to expand the Seed Token into a Map Token, such as calculating a gradient color palette from a basic color, or calculating rounded corners of various sizes from a basic rounded corner. Algorithms can be used alone or in any combination, for example, dark and compact algorithms can be combined to get a dark and compact theme. ```tsx import { theme } from 'antd'; const { darkAlgorithm, compactAlgorithm } = theme; const theme = { algorithm: [darkAlgorithm, compactAlgorithm], }; ``` ### Legacy Browser Compatible Please ref to [CSS Compatible](/docs/react/compatible-style). ### Server Side Render (SSR) There are two options for server-side rendering styles, each with advantages and disadvantages: - **Inline mode**: there is no need to request additional style files during rendering. The advantage is to reduce additional network requests. The disadvantage is that the HTML volume will increase and the speed of the first screen rendering will be affected. Relevant discussion: [#39891](https://github.com/ant-design/ant-design/issues/39891) - **Whole export**: The antd component is pre-baked and styled as a css file to be introduced in the page. The advantage is that when opening any page, the same set of css files will be reused just like the traditional css scheme to hit the cache. The disadvantage is that if there are multiple themes in the page, additional baking is required #### Inline mode Use `@ant-design/cssinjs` to extract style: ```tsx import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs'; import { renderToString } from 'react-dom/server'; export default () => { // SSR Render const cache = createCache(); const html = renderToString( , ); // Grab style from cache const styleText = extractStyle(cache); // Mix with style return ` ${styleText}
${html}
`; }; ``` #### Whole export If you want to detach a style file into a css file, try the following schemes: 1. Installation dependency ```bash npm install ts-node tslib cross-env --save-dev ``` 2. Add `tsconfig.node.json` ```json { "compilerOptions": { "strictNullChecks": true, "module": "NodeNext", "jsx": "react", "esModuleInterop": true }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"] } ``` 3. Add `scripts/genAntdCss.tsx` ```tsx // scripts/genAntdCss.tsx import { extractStyle } from '@ant-design/static-style-extract'; import fs from 'fs'; const outputPath = './public/antd.min.css'; const css = extractStyle(); fs.writeFileSync(outputPath, css); ``` If you want to use mixed themes or custom themes, you can use the following script: ```tsx import { extractStyle } from '@ant-design/static-style-extract'; import { ConfigProvider } from 'antd'; import fs from 'fs'; import React from 'react'; const outputPath = './public/antd.min.css'; const testGreenColor = '#008000'; const testRedColor = '#ff0000'; const css = extractStyle((node) => ( <> {node} {node} )); fs.writeFileSync(outputPath, css); ``` You can choose to execute this script before starting the development command or before compiling. Running this script will generate a full antd.min.css file directly in the specified directory of the current project (e.g. public). Take Next.js for example([example](https://github.com/ant-design/create-next-app-antd)): ```json // package.json { "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "predev": "ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx", "prebuild": "cross-env NODE_ENV=production ts-node --project ./tsconfig.node.json ./scripts/genAntdCss.tsx" } } ``` Then, you just need to import this file into the `pages/_app.tsx` file: ```tsx import { StyleProvider } from '@ant-design/cssinjs'; import type { AppProps } from 'next/app'; import '../public/antd.min.css'; import '../styles/globals.css'; // add this line export default function App({ Component, pageProps }: AppProps) { return ( ); } ``` #### Custom theme If you're using a custom theme for your project, try baking in the following ways: ```tsx import { extractStyle } from '@ant-design/static-style-extract'; import { ConfigProvider } from 'antd'; const cssText = extractStyle((node) => ( {node} )); ``` #### Mixed theme If you're using a mixed theme for your project, try baking in the following ways: ```tsx import { extractStyle } from '@ant-design/static-style-extract'; import { ConfigProvider } from 'antd'; const cssText = extractStyle((node) => ( <> {node} {node} )); ``` More about static-style-extract, see [static-style-extract](https://github.com/ant-design/static-style-extract). #### Export the css files on demand ```tsx // scripts/genAntdCss.tsx import { extractStyle } from '@ant-design/cssinjs'; import type Entity from '@ant-design/cssinjs/lib/Cache'; import { createHash } from 'crypto'; import fs from 'fs'; import path from 'path'; export type DoExtraStyleOptions = { cache: Entity; dir?: string; baseFileName?: string; }; export function doExtraStyle({ cache, dir = 'antd-output', baseFileName = 'antd.min', }: DoExtraStyleOptions) { const baseDir = path.resolve(__dirname, '../../static/css'); const outputCssPath = path.join(baseDir, dir); if (!fs.existsSync(outputCssPath)) { fs.mkdirSync(outputCssPath, { recursive: true }); } const css = extractStyle(cache, true); if (!css) return ''; const md5 = createHash('md5'); const hash = md5.update(css).digest('hex'); const fileName = `${baseFileName}.${hash.substring(0, 8)}.css`; const fullpath = path.join(outputCssPath, fileName); const res = `_next/static/css/${dir}/${fileName}`; if (fs.existsSync(fullpath)) return res; fs.writeFileSync(fullpath, css); return res; } ``` Export on demand using the above tools in `_document.tsx` ```tsx // _document.tsx import { StyleProvider, createCache } from '@ant-design/cssinjs'; import Document, { DocumentContext, Head, Html, Main, NextScript } from 'next/document'; import { doExtraStyle } from '../scripts/genAntdCss'; export default class MyDocument extends Document { static async getInitialProps(ctx: DocumentContext) { const cache = createCache(); let fileName = ''; const originalRenderPage = ctx.renderPage; ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => ( ), }); const initialProps = await Document.getInitialProps(ctx); // 1.1 extract style which had been used fileName = doExtraStyle({ cache, }); return { ...initialProps, styles: ( <> {initialProps.styles} {/* 1.2 inject css */} {fileName && } ), }; } render() { return (
); } } ``` See the demo:[Export the css files on demand demo](https://github.com/ant-design/create-next-app-antd/tree/generate-css-on-demand) ### Shadow DOM Usage Since `