logoAnt Design

⌘ K
  • Design
  • Development
  • Components
  • Blog
  • Resources
5.25.4
  • Ant Design of React
  • Changelog
    v5.25.4
  • Basic Usage
    • Getting Started
    • Usage with Vite
    • Usage with Next.js
      Updated
    • Usage with Umi
    • Usage with Rsbuild
    • Usage with Farm
    • Usage with Refine
  • Advanced
    • Customize Theme
    • CSS Compatible
    • Server Side Rendering
    • CSS Variables
      New
    • Use custom date library
    • Internationalization
    • Common Props
    • React 19 Compatibility
      New
  • Migration
    • V4 to V5
    • Less variables to Component Token
  • Other
    • Third-Party Libraries
    • Contributing
    • FAQ
Inline Style
Whole Export
Custom theme
Mixed theme
Extract on demand

Server Side Rendering

contributors
  • CSS CompatibleCSS Variables

    Resources

    Ant Design X
    Ant Design Charts
    Ant Design Pro
    Pro Components
    Ant Design Mobile
    Ant Design Mini
    Ant Design Web3
    Ant Design Landing-Landing Templates
    Scaffolds-Scaffold Market
    Umi-React Application Framework
    dumi-Component doc generator
    qiankun-Micro-Frontends Framework
    Ant Motion-Motion Solution
    China Mirror 🇨🇳

    Community

    Awesome Ant Design
    Medium
    Twitter
    yuque logoAnt Design in YuQue
    Ant Design in Zhihu
    Experience Cloud Blog
    seeconf logoSEE Conf-Experience Tech Conference

    Help

    GitHub
    Change Log
    FAQ
    Bug Report
    Issues
    Discussions
    StackOverflow
    SegmentFault

    Ant XTech logoMore Products

    yuque logoYuQue-Document Collaboration Platform
    AntV logoAntV-Data Visualization
    Egg logoEgg-Enterprise Node.js Framework
    Kitchen logoKitchen-Sketch Toolkit
    Galacean logoGalacean-Interactive Graphics Solution
    xtech logoAnt Financial Experience Tech
    Theme Editor
    Made with ❤ by
    Ant Group and Ant Design Community

    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
    • 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 Style

    Use @ant-design/cssinjs to extract style:

    tsx
    import React from 'react';
    import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
    import type Entity from '@ant-design/cssinjs/es/Cache';
    import { renderToString } from 'react-dom/server';
    const App = () => {
    // SSR Render
    const cache = React.useMemo<Entity>(() => createCache(), []);
    const html = renderToString(
    <StyleProvider cache={cache}>
    <MyApp />
    </StyleProvider>,
    );
    // Grab style from cache
    const styleText = extractStyle(cache);
    // Mix with style
    return `
    <!DOCTYPE html>
    <html>
    <head>
    ${styleText}
    </head>
    <body>
    <div id="root">${html}</div>
    </body>
    </html>
    `;
    };
    export default App;

    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
    1. Add tsconfig.node.json
    json
    {
    "compilerOptions": {
    "strictNullChecks": true,
    "module": "NodeNext",
    "jsx": "react",
    "esModuleInterop": true
    },
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
    }
    1. Add scripts/genAntdCss.tsx
    tsx
    // scripts/genAntdCss.tsx
    import fs from 'fs';
    import { extractStyle } from '@ant-design/static-style-extract';
    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 fs from 'fs';
    import React from 'react';
    import { extractStyle } from '@ant-design/static-style-extract';
    import { ConfigProvider } from 'antd';
    const outputPath = './public/antd.min.css';
    const testGreenColor = '#008000';
    const testRedColor = '#ff0000';
    const css = extractStyle((node) => (
    <>
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: testGreenColor,
    },
    }}
    >
    {node}
    </ConfigProvider>
    <ConfigProvider
    theme={{
    token: {
    colorPrimary: testGreenColor,
    },
    }}
    >
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: testRedColor,
    },
    }}
    >
    {node}
    </ConfigProvider>
    </ConfigProvider>
    </>
    ));
    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):

    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'; // add this line
    import '../styles/globals.css';
    export default function App({ Component, pageProps }: AppProps) {
    return (
    <StyleProvider hashPriority="high">
    <Component {...pageProps} />
    </StyleProvider>
    );
    }

    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) => (
    <ConfigProvider
    theme={{
    token: {
    colorPrimary: 'red',
    },
    }}
    >
    {node}
    </ConfigProvider>
    ));

    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) => (
    <>
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: 'green ',
    },
    }}
    >
    {node}
    </ConfigProvider>
    <ConfigProvider
    theme={{
    token: {
    colorPrimary: 'blue',
    },
    }}
    >
    <ConfigProvider
    theme={{
    token: {
    colorBgBase: 'red ',
    },
    }}
    >
    {node}
    </ConfigProvider>
    </ConfigProvider>
    </>
    ));

    More about static-style-extract, see static-style-extract.

    Extract on demand

    tsx
    // scripts/genAntdCss.tsx
    import { createHash } from 'crypto';
    import fs from 'fs';
    import path from 'path';
    import { extractStyle } from '@ant-design/cssinjs';
    import type Entity from '@ant-design/cssinjs/lib/Cache';
    export interface DoExtraStyleOptions {
    cache: Entity;
    dir?: string;
    baseFileName?: string;
    }
    export const doExtraStyle = (opts: DoExtraStyleOptions) => {
    const { cache, dir = 'antd-output', baseFileName = 'antd.min' } = opts;
    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 { createCache, StyleProvider } from '@ant-design/cssinjs';
    import type { DocumentContext } from 'next/document';
    import Document, { 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) => (
    <StyleProvider cache={cache}>
    <App {...props} />
    </StyleProvider>
    ),
    });
    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 && <link rel="stylesheet" href={`/${fileName}`} />}
    </>
    ),
    };
    }
    render() {
    return (
    <Html lang="en">
    <Head />
    <body>
    <Main />
    <NextScript />
    </body>
    </Html>
    );
    }
    }

    See the demo:Export the css files on demand demo