# ant-design Best Practices
This guide outlines the definitive best practices for using Ant Design v6.x in our projects. Adhering to these standards ensures consistency, accessibility, and maintainability across our codebase.
## 1. Theming: Design Token Driven
Always customize Ant Design's appearance using its design token system via `ConfigProvider`. Avoid direct CSS overrides for visual properties that can be controlled by tokens.
### ✅ GOOD: Centralized Token Customization
Create a `theme.ts` file to export your theme configuration and apply it at the root of your application. Prefer `seedToken` adjustments for global changes and `componentToken` for specific component overrides. Utilize preset algorithms for light/dark mode.
```typescript // src/theme.ts import { theme } from 'antd'; import type { ThemeConfig } from 'antd';
export const appTheme: ThemeConfig = { algorithm: theme.defaultAlgorithm, // Or theme.darkAlgorithm, [theme.defaultAlgorithm, theme.darkAlgorithm] token: { colorPrimary: '#0050B3', // Our primary brand color colorSuccess: '#52C41A', fontSize: 14, borderRadius: 4, // Disable motion globally for accessibility/performance motion: false, }, components: { Button: { colorPrimary: '#1890FF', // Override primary button color algorithm: true, // Enable algorithm for component token derivation }, Layout: { headerBg: '#001529', footerBg: '#F0F2F5', }, }, }; ```
```tsx // src/App.tsx (or root layout) import React from 'react'; import { ConfigProvider, App as AntdApp } from 'antd'; import { appTheme } from './theme'; import HomePage from './pages/HomePage';
const App: React.FC = () => { return ( <ConfigProvider theme={appTheme}> {/* Use AntdApp for context-aware static methods (message, Modal, notification) */} <AntdApp> <HomePage /> </AntdApp> </ConfigProvider> ); };
export default App; ```
### ❌ BAD: Direct CSS Overrides
Avoid overriding Ant Design component styles with custom CSS classes or inline styles for properties that are themeable. This leads to inconsistent UIs and breaks theme updates.
```css /* ❌ BAD: Avoid this for themeable properties */ .ant-btn-primary { background-color: #f00 !important; /* Breaks theme */ border-color: #f00 !important; } ```
## 2. Layout: Unified Grid System
Adhere to Ant Design's 8-pixel grid unit and the unified 1440px canvas width. Use `Row` and `Col` components for structural layout, leveraging their `span` and `gutter` props.
### ✅ GOOD: Responsive Layout with Grid
```tsx import React from 'react'; import { Layout, Row, Col } from 'antd';
const { Header, Content, Footer } = Layout;
const MyLayout: React.FC = () => ( <Layout style={{ minHeight: '100vh' }}> <Header style={{ backgroundColor: '#001529' }}> {/* Header content */} </Header> <Content style={{ padding: '0 50px', maxWidth: 1440, margin: '16px auto' }}> <Row gutter={[16, 16]}> {/* 16px horizontal and vertical gutter */} <Col span={24}> <h1>Welcome to our Application</h1> </Col> <Col xs={24} sm={12} md={8}> {/* Responsive columns */} <div style={{ background: '#fff', padding: 24, minHeight: 120 }}> Card 1 </div> </Col> <Col xs={24} sm={12} md={8}> <div style={{ background: '#fff', padding: 24, minHeight: 120 }}> Card 2 </div> </Col> <Col xs={24} sm={24} md={8}> <div style={{ background: '#fff', padding: 24, minHeight: 120 }}> Card 3 </div> </Col> </Row> </Content> <Footer style={{ textAlign: 'center' }}> Ant Design ©{new Date().getFullYear()} Created by Ant UED </Footer> </Layout> );
export default MyLayout; ```
### ❌ BAD: Hardcoding Layout Dimensions
Avoid using fixed pixel values or custom CSS for spacing and alignment that should be handled by the grid system or design tokens.
```tsx // ❌ BAD: Avoid custom margins for layout <div style={{ marginLeft: '20px', paddingRight: '30px' }}> {/* Content */} </div> ```
## 3. Component Usage: Standardized & Accessible
Import components directly from `antd`. Always use TypeScript and configure ESLint with `eslint-plugin-antd` to enforce best practices. Prioritize accessibility by providing necessary `aria-*` attributes.
### ✅ GOOD: Proper Imports and Accessibility
```tsx import React from 'react'; import { Button, Space, Typography } from 'antd'; import { PlusOutlined } from '@ant-design/icons';
const { Text } = Typography;
const MyComponent: React.FC = () => { const handleClick = () => { console.log('Button clicked'); };
return ( <Space> <Button type="primary" onClick={handleClick} icon={<PlusOutlined />} aria-label="Add new item"> Add Item </Button> <Text strong>Important information.</Text> </Space> ); };
export default MyComponent; ```
### ❌ BAD: Missing Accessibility Attributes
Interactive components must have appropriate `aria-*` attributes for screen reader users.
```tsx // ❌ BAD: Missing aria-label for icon-only button <Button icon={<PlusOutlined />} onClick={() => {}} /> ```
## 4. Internationalization & SSR
Wrap your root component with `ConfigProvider` to set the locale and theme. For Server-Side Rendering (SSR), follow the official Ant Design SSR guide to prevent hydration mismatches.
### ✅ GOOD: Global Locale Configuration
```tsx // src/main.tsx (or root entry) import React from 'react'; import { createRoot } from 'react-dom/client'; import { ConfigProvider } from 'antd'; import enUS from 'antd/locale/en_US'; // Import desired locale import App from './App'; import { appTheme } from './theme';
const container = document.getElementById('root'); const root = createRoot(container!);
root.render( <React.StrictMode> <ConfigProvider locale={enUS} theme={appTheme}> <App /> </ConfigProvider> </React.StrictMode> ); ```
## 5. Performance: Zero Runtime & Tree Shaking
Leverage Ant Design's `zeroRuntime` mode (v6.0.0+) in production for improved performance by pre-generating styles. Ensure your build setup supports tree shaking for `antd` to minimize bundle size.
### ✅ GOOD: Zero Runtime Mode in Production
For production builds, enable `zeroRuntime` and import the pre-generated CSS.
```tsx // src/App.tsx import React from 'react'; import { ConfigProvider, App as AntdApp } from 'antd'; import { appTheme } from './theme'; import HomePage from './pages/HomePage';
// In production, import the static CSS generated by @ant-design/static-style-extract // import 'antd/dist/antd.css'; // Or your custom extracted CSS file
const App: React.FC = () => { // In a real app, you'd conditionally apply zeroRuntime based on NODE_ENV const isProduction = process.env.NODE_ENV === 'production';
return ( <ConfigProvider theme={{ ...appTheme, zeroRuntime: isProduction }}> <AntdApp> <HomePage /> </AntdApp> </ConfigProvider> ); };
export default App; ```
### ❌ BAD: Importing Full CSS with Runtime Styling
If `zeroRuntime` is `false` (default for development), avoid importing `antd/dist/antd.css` as it will lead to duplicate styles and larger bundle sizes.
```tsx // ❌ BAD: If zeroRuntime is false, this is redundant and harmful import 'antd/dist/antd.css'; ```
## 6. Hooks Best Practices
Utilize Ant Design's hooks for accessing theme tokens and managing context-aware static methods.
### ✅ GOOD: Using `useToken` and `App` Component
```tsx import React from 'react'; import { Button, theme, message } from 'antd'; import { App as AntdApp } from 'antd'; // Import App component for static methods
const MyThemedComponent: React.FC = () => { const { token } = theme.useToken(); // Access current theme tokens const [messageApi, contextHolder] = message.useMessage(); // For context-aware message
const showInfo = () => { messageApi.info(`Primary color: ${token.colorPrimary}`); };
return ( <div> {contextHolder} {/* Important: Render contextHolder */} <Button onClick={showInfo} style={{ backgroundColor: token.colorPrimary, color: token.colorTextLightSolid }}> Show Primary Color </Button> </div> ); };
// Wrap components that use static methods or useToken inside <AntdApp> const RootComponent: React.FC = () => ( <AntdApp> <MyThemedComponent /> </AntdApp> );
export default RootComponent; ```
### ❌ BAD: Static Methods Without Context
Calling `message.info()` or `Modal.confirm()` directly without `App` component or `useMessage`/`useModal` hooks will result in them not inheriting `ConfigProvider` context (e.g., theme, locale).
```tsx // ❌ BAD: This message will not inherit ConfigProvider context import { message, Button } from 'antd';
const BadComponent: React.FC = () => ( <Button onClick={() => message.info('Hello')}> Show Message </Button> ); ```