Design systems
Blue Design Tokens: Tailwind, Material, and Ant Design Compared
Compare familiar blue tokens, check their palette versions, and map them to semantic UI roles without assuming matching names mean matching colors.
A token name needs a palette version
A label such as blue-500 identifies a position inside a particular palette. It does not define a universal blue. Tailwind CSS, Material Design, and Ant Design use different naming systems and different values, even when their tokens fill a similar role in a product.
Record the library, palette version, token name, and actual color together. Tailwind v3 uses HEX palette values; Tailwind v4 defines its default colors in OKLCH. The #3B82F6 example in this guide is the Tailwind v3 blue-500 reference. Check the installed version and resolved CSS variable before migrating it into another project.
Separate palette, semantic, and component decisions
A practical token model has three levels. A palette token stores a reusable value, such as palette-blue-600. A semantic token assigns a purpose, such as action-background. A component token describes a specific use, such as button-primary-background. These levels can reference one another, allowing a brand adjustment to propagate while preserving intentional exceptions in individual components.
For example, a primary button and an inline link may start with the same blue, but they have different constraints. The button needs a readable label against its fill; the link needs readable text against the page surface and a way to remain identifiable within surrounding prose. Giving both components a single token named brand-blue makes those independent requirements harder to maintain.
Ant Design documents its own Seed, Map, and Alias Token lifecycle. A seed such as colorPrimary contributes to derived theme values; it is not a guarantee that every rendered primary state uses the seed unchanged. When integrating a component library, inspect its resolved theme and component overrides before creating your application-level semantic mapping.
Compare actual values before assigning roles
These examples are reference points from explicitly named palettes. Material Design's 2014 Indigo 500 is not the same system as Material 3's generated tonal palettes. Ant Design's default primary seed can also be customized, so a product theme may resolve to a different color.
The similar-looking blues below should not be swapped without checking text contrast, hover states, and surrounding surfaces. Convert each value into the format used by your implementation, then compare the results in the real component.
| Palette reference | Token | HEX | RGB |
|---|---|---|---|
| Tailwind CSS v3 | blue-500 | #3B82F6 | 59, 130, 246 |
| Material Design 2014 | Indigo 500 | #3F51B5 | 63, 81, 181 |
| Material Design 2014 | Light Blue 500 | #03A9F4 | 3, 169, 244 |
| Ant Design v5 default | colorPrimary / blue-6 | #1677FF | 22, 119, 255 |
Keep the color space visible during comparison
HEX and integer RGB describe the same sRGB channels when the value is opaque. Changing #3B82F6 to rgb(59, 130, 246) therefore changes notation without creating a new palette. OKLCH expresses lightness, chroma, and hue instead. Its coordinates cannot be copied into RGB channels or compared numerically with a HEX string to establish that two tokens are equivalent.
Tailwind v4's documented palette uses OKLCH, so retain that original definition when your pipeline supports it. If an export requires HEX, record how the color was converted and how any colors outside the destination gamut were handled. An sRGB approximation can lose chroma; it should not silently replace the source definition in the design system.
For a fair review, compare tokens on the same surface, in the same color space, and with the same component geometry. A palette step such as 500 does not specify a shared lightness across different libraries. Use visual inspection for brand intent and a measured contrast ratio for text readability; neither check substitutes for the other.
Map palette values to semantic tokens
Keep the raw palette separate from a component's purpose. A semantic name such as action-background makes it clear why a color exists. It also lets you change a library palette without renaming every button and link in the application.
In this Tailwind v3 example, the normal button uses blue-600 rather than blue-500. White text on #3B82F6 has about 3.68:1 contrast, which falls below WCAG AA's 4.5:1 requirement for normal text. White on #2563EB has about 5.17:1. The darker value is a deliberate component choice, not a claim that one palette is universally better.
:root {
/* Tailwind CSS v3 palette references */
--palette-blue-500: #3b82f6;
--palette-blue-600: #2563eb;
--palette-blue-700: #1d4ed8;
--action-background: var(--palette-blue-600);
--action-background-hover: var(--palette-blue-700);
--action-text: #ffffff;
}
.button {
background: var(--action-background);
color: var(--action-text);
}
.button:hover {
background: var(--action-background-hover);
}Define a state matrix for light and dark themes
List the actual foreground and background pair for each supported state: default, hover, pressed, selected, and keyboard focus. Include the page surface when a button is transparent or outlined. A darker hover fill can improve white-label contrast, while a pale selected surface usually needs a separate dark foreground. Check the resolved pair rather than assuming that moving one palette step always improves the component.
Dark mode needs its own role mapping. Reversing the palette or reusing the light theme's action color can produce links that disappear into a dark surface or focus rings that merge with the button. Derive the theme using the library's supported mechanism, then verify the resulting labels, borders, and indicators on the surfaces where they actually appear.
Document state-specific exceptions beside their reason. For example, a brand blue may remain appropriate for an illustration while a darker action token is used for a small white button label. This keeps the brand reference stable and makes the accessibility decision reviewable. The CSS example above illustrates token references; a complete button still needs keyboard focus styling and interaction behavior.
Validate a migration in the component
First inventory the values your current theme actually outputs, including overrides. Next map the semantic roles: action, link, focus indicator, selected surface, and text. Do not replace every occurrence of a blue simply because it shares a numeric step with the new palette.
Check the normal, hover, active, and focus states against their adjacent colors. Test text on the final background, including transparency and overlays. Keep a visible focus indicator and another cue for links or status; color alone should not carry the entire meaning.
Finally record the new palette version and the contrast results beside your design tokens. Use the reference pages below to inspect exact values, then use the analyzer to verify the foreground and background chosen for your interface.
A useful migration record includes the old value, new semantic token, resolved value in each theme, affected components, and the measured contrast pairs. Review one representative component before replacing every reference. A screenshot can reveal visual regressions, but the stored measurements explain why a change is acceptable and allow the next library upgrade to repeat the same checks.