← Back to all posts

Building a Modern Design System with CSS Custom Properties

Building a Modern Design System with CSS Custom Properties

CSS Custom Properties, often called CSS variables, let teams express design decisions as reusable values. Colors, spacing, typography, borders, and motion can be defined once and consumed by every component that belongs to the same visual system.

Start with design tokens

A token should describe a design role rather than one isolated element. Names such as --color-action or --space-section communicate intent more clearly than names tied to a single button or page.

:root {
    --color-brand: #2a7ea8;
    --color-surface: #ffffff;
    --color-text: #1f2933;
    --space-sm: 0.5rem;
    --space-md: 1rem;
    --radius-lg: 1.125rem;
}

Use tokens inside components

Components become easier to understand when their values refer back to the shared vocabulary:

.button {
    background: var(--color-brand);
    color: var(--color-surface);
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-lg);
}

A token does not eliminate every local value. Component-specific geometry can remain local when it has no broader meaning. The goal is consistency, not turning every number into a global variable.

Responsive values

Custom Properties participate in the cascade, so a breakpoint can update a shared value without duplicating every rule that consumes it.

:root {
    --space-section: 3rem;
}

@media (min-width: 768px) {
    :root {
        --space-section: 5rem;
    }
}

Light and dark themes

Semantic color tokens also make themes straightforward:

:root {
    --color-background: #ffffff;
    --color-foreground: #222222;
}

[data-theme="dark"] {
    --color-background: #15191d;
    --color-foreground: #f5f7f9;
}

Components continue to use the semantic variables and do not need theme-specific selectors. When adding themes, verify contrast, focus indicators, images, shadows, and browser-native controls—not just background and text colors.

Practical conventions

  • Keep global tokens in one documented layer.
  • Use consistent naming for color, size, spacing, and typography scales.
  • Provide sensible fallbacks when a component may be reused outside the main application.
  • Avoid deeply chained variables that make the final value difficult to trace.
  • Review unused tokens and remove them as the system evolves.

Conclusion

CSS Custom Properties turn visual decisions into a maintainable interface between design and code. A small, intentional token system improves consistency today and gives future components, themes, and responsive layouts a stable foundation.