Before Ant Design v6, the experience of customizing styles based on open tokens was already great, but there were still some pain points that were difficult to solve. Ant Design v6 made many changes and improvements to address this. Today, let’s talk about how semantic design helps you discover the delicate beauty of components.
In the past, how did we typically adjust component styles?
className and style attributeswrapClassName when modifying styles of different component regionsThe code might look like this:
<Button className={variant === 'filled' ? 'btn-filled' : 'btn-outline'}>Submit</Button><Modal wrapClassName="wrap-class" style={{ backgroundColor: '#fff' }}>Modal</Modal><Menu style={{ backgroundColor: mode === 'horizontal' ? '#fff' : '#000' }}><Menu.SubMenu popupClassName="popup-class"><Menu.Item >MenuItem</Menu.Item></Menu.SubMenu></Menu>
Using the theme Design Token design introduced in Ant Design v5:
<ConfigProvidertheme={{components: {Notification: {colorTextHeading: token.blue,colorText: token.colorTextSecondary,},},}}>{children}</ConfigProvider>
Apart from these two methods, you might also have written less recommended CSS overrides:
.wrapper-class .ant-table {border-radius: 4px;overflow: hidden;}.wrapper-class .ant-table .ant-table-thead {background-color: #f9fafc;color: #8b97b6;}
All of the above approaches have various pain points:
props make it impossible to modify certain regions, and logic is not well-organizedDesign Token configuration prevents differentiated styling based on different types/variantsTo avoid token proliferation and the addition of numerous API props — which would increase maintenance costs — these elements were consolidated into a more semantic structure.
const classNamesFn: ButtonProps['classNames'] = (info) => {if (info.props.type === 'primary') {return {root: 'demo-btn-root--primary',} satisfies ButtonProps['classNames'];}return {root: 'demo-btn-root--default',} satisfies ButtonProps['classNames'];};const styles: ButtonProps['styles'] = {root: { borderWidth: 2, borderStyle: 'dashed' },content: { fontStyle: 'italic' },icon: { opacity: 0.85 },};return (<Button styles={styles} classNames={classNamesFn}>Button</Button>);
What's more exciting is that the classNames property integrates perfectly with atomic CSS frameworks like Tailwind CSS. This provides developers with unprecedented freedom: you can enjoy the preset behavior and semantic structure of antd components while leveraging Tailwind's utility classes to quickly build any visual style you want. Semantic design + Tailwind CSS, makes component customization extremely flexible.
return (<ButtonclassNames={{root: 'bg-black text-white border-none hover:bg-[#2e2e2e]',icon: 'text-white/90',}}icon={<GiftOutlined />}>Ant Design</Button>);
Users can give components refined designs for different states based on their preferred color schemes. Let your imagination run wild and make your pages more vibrant and expressive. If you encounter any issues or have better ideas during use, feel free to share feedback — let’s make Ant Design even better together.
In Ant Design’s design system, tokens are positioned as design variables — the atomic materials of the design language. Semantic styles, on the other hand, define how those materials are used. They are created by combining design tokens with component-level customizations, allowing for more flexible and expressive styling scenarios. Since semantic styles operate at the component level, they provide better control over styling scope. If you aim to design a fully customized Ant Design theme, the combination of tokens and semantic styling will be your most powerful tool — together, they enable you to craft a more refined and precisely tailored theme.