DEV Community

Nainik Mehta
Nainik Mehta

Posted on

Migrate to Ant Design v6: zeroRuntime & CSS Variables

Why Ant Design v6 matters

Ant Design v6 is a technical, performance-first upgrade. It modernizes the styling engine around CSS variables, raises the minimum React version to 18, and introduces a zeroRuntime mode that can dramatically reduce runtime cost and bundle size. If you maintain a production UI built on Ant Design, planning an Ant Design v6 migration is a great opportunity to remove legacy workarounds and optimize theming and CSS delivery — but the change also has concrete gotchas that will bite if you rush it.

Before you upgrade: hard preconditions

Treat v6 as a checkpoint you must pass before flipping the switch:

  • Upgrade to React 18 or newer. v6 drops support for React ≤17.
  • Bump your icons package: upgrade @ant-design/icons to v6+. Note: @ant-design/icons@6 is not compatible with antd@5, so upgrade them together.
  • Remove any v5 React-19 patches (e.g., @ant-design/v5-patch-for-react-19) — v6 assumes the newer React runtime semantics.
  • Confirm your browser support: v6 uses CSS variables by default and no longer supports IE.

Also: before moving to v6, upgrade to the latest v5 and fix console deprecation warnings. v6 expects a clean codebase; unresolved deprecations can hide runtime surprises.

The most common runtime gotcha: undefined themes

ConfigProvider drives theming in v6 via a DesignTokenContext. If theme is undefined, the provider layer may be omitted and components can be re-mounted unexpectedly. In our team’s migration a lazily-loaded theme value was briefly undefined during a render, and ConfigProvider attempted to read token at render — styles failed and components remounted.

Guard your theme values by normalizing undefined to an empty object and providing a token fallback. Example:

const tokens = config?.token ?? {};

That small pattern prevents component remounts and runtime crashes caused by missing ConfigProvider context.

ZeroRuntime: huge wins, but choose carefully

zeroRuntime disables Ant Design’s runtime style generation and switches to a pure CSS-variables architecture. Benefits:

  • Faster page start-up and reduced runtime CPU.
  • Smaller JS work at render time.
  • Better multi-theme reuse by switching CSS variables rather than recalculating styles.

Trade-offs:

  • If your app relies on dynamic runtime token swapping (for example, swapping tokens per user session or computed theme adjustments on the fly), zeroRuntime forces you to re-think the pattern. You’ll either need to precompute variants at build time, inject computed CSS variables yourself, or limit dynamic theming to the variables you can swap at runtime.
  • You must import component CSS manually or extract static CSS for the components you use; runtime generation no longer supplies it for you.

Enable zeroRuntime via ConfigProvider when you’re ready:

Static CSS extraction with @ant-design/static-style-extract

If you enable zeroRuntime, don’t bundle the entire antd stylesheet. Use @ant-design/static-style-extract to generate only the CSS you need at build time. Example usage (Node script):

import fs from 'fs';
import { extractStyle } from '@ant-design/static-style-extract';

const cssText = extractStyle({
includes: ['Button', 'Form', 'Input'], // include the components you use
// optional: pass theme information or cssVar config if needed
});

fs.writeFileSync('./dist/antd.extract.css', cssText);

Serve the extracted CSS in production alongside your app bundle. This reduces payload and avoids shipping unused component styles.

Watch semantic DOM and CSS selector changes

v6 refactors internal component DOM in places. If you target Ant Design internal classes or element structure from your CSS, audit and rewrite those rules.

Concrete example: our code had a custom override targeting .ant-btn > span. v6 moved internal spans and the rule stopped applying. Fix it by:

  • Switching to token overrides (preferred), or
  • Using a top-level documented selector or component-level class name, or
  • Wrapping the component with a small className and scoping styles to that wrapper.

Token-driven overrides are safer because they rely on the documented theming API rather than internal DOM:

Where possible, prefer documented style hooks (ConfigProvider.styles, component-level tokens, or theme.useToken()) instead of brittle selectors.

Practical migration checklist (step-by-step)

  1. Upgrade to latest v5 and resolve all deprecation warnings. Use the Ant Design CLI if you want automated hints.
  2. Update React to 18+ and remove any v5 React patches. Run your test suite and linting.
  3. Upgrade @ant-design/icons to v6 alongside antd@6.
  4. Audit browser support and confirm CSS variables are acceptable for your users.
  5. Decide if you’ll enable zeroRuntime. If yes:
    • Plan static CSS extraction for only used components.
    • Replace any runtime theme-swapping logic with precomputed CSS variable approaches or a controlled runtime CSS injection strategy.
  6. Replace undefined themes with {} and add token fallbacks to ConfigProvider to avoid re-mounts.
  7. Scan for selectors targeting internal DOM (e.g., .ant-... > span) and migrate those rules to tokens or safer selectors.
  8. Test overlay components (Modal/Drawer) and be aware of the mask blur default differences in early v6 releases — configure modal.mask.blur/drawer.mask.blur if needed.
  9. Run end-to-end tests and performance checks, paying attention to initial render time and CSS size.

Final thoughts

Treat Ant Design v6 migration as a performance-first change. The biggest wins come from embracing tokens, extracting static CSS, and removing runtime style assumptions. The common gotchas — undefined themes, brittle internal selectors, and dynamic runtime theming expectations — are solvable with a few defensive patterns and a short migration checklist.

Have a single migration gotcha you dread? For many teams it’s “mysterious styling breakages” caused by internal DOM changes. The medicinal approach: move to token-based overrides, extract only what you need, and normalize theme values before they reach ConfigProvider.

Happy migrating — and remember: plan, test, extract, and prefer documented APIs over internal structures.

Top comments (0)