🌈 ~khtdr/

home / Software / css-vars-design-token

CSS Variables as Design Tokens: A Simple Approach to Design Systems

Design systems are essential in modern web development. They help maintain consistency, speed up development, and ensure a cohesive user experience across applications. For small teams or even solo developers, a design system can really make things easier. It cuts down on repeated design decisions by providing reusable components and design guidelines and allowing developers to focus on building features instead of worrying about inconsistencies. This leads to faster iterations, easier onboarding for new team members, and a more unified product.

CSS variables, or custom properties, are entities defined by CSS that let you store values for reuse throughout a document. They enable dynamic styling and can be updated at runtime, making them a powerful tool for creating flexible and maintainable design systems.

Why CSS Variables Are Good Enough

While there are many sophisticated design token solutions available, native CSS variables have evolved to be remarkably capable:

  • They're built into the platform
  • They cascade naturally through the DOM
  • They can be updated dynamically
  • They work with any framework (or no framework)
  • They're performant
  • Browser support is excellent

Introducing css-vars-design-token

The css-vars-design-token package offers a lightweight approach to design tokens using CSS variables. It provides:

  1. Simple theme switching
  2. TypeScript support
  3. React integration
  4. Zero dependencies beyond React itself

Basic Usage

Here's a simple example:

// Create the `light` and `dark` themes.
const themes = {
    light: {
        color: {
            primary: '#0066cc',
            background: '#ffffff',
            text: '#333333'
        }
    },
    dark: {
        color: {
            primary: '#66b3ff',
            background: '#1a1a1a',
            text: '#ffffff'
        }
    }
};

// Wrap your components in a provider
function App() {
    return (
        <CssVarsDesignTokenProvider themes={themes}>
            <MyComponents />
        </CssVarsDesignTokenProvider>
    );
}

Your CSS can then use these tokens:

.button {
    background-color: var(--color-primary);
    color: var(--color-text);
}

.card {
    background-color: var(--color-background);
    border: 1px solid var(--color-primary);
}

Advanced Features

Deep Tokens

The library automatically flattens deep token structures:

const themes = {
    light: {
        spacing: {
            small: '0.5rem',
            medium: '1rem',
            large: {
                default: '2rem',
                mobile: '1.5rem'
            }
        }
    }
};

This creates CSS variables like --spacing-small, --spacing-medium, --spacing-large-default, and --spacing-large-mobile.

Theme Switching

The library provides a hook for easy theme switching:

function ThemeToggle() {
    const { theme, toggle } = useCssVarsDesignTokenContext();
    return (
        <button onClick={toggle}>
            Current theme: {theme}
        </button>
    );
}

Real-World Applications

Responsive Design

CSS variables work seamlessly with media queries:

:root {
    --sidebar-width: var(--layout-sidebar-default);
}

@media (max-width: 768px) {
    :root {
        --sidebar-width: var(--layout-sidebar-compact);
    }
}

Component Libraries

Design tokens can help create consistent component libraries:

function Button({ variant = 'primary', children }) {
    return (
        <button
            style={{
                backgroundColor: `var(--color-${variant})`,
                padding: 'var(--spacing-medium)',
                borderRadius: 'var(--border-radius-medium)'
            }}
        >
            {children}
        </button>
    );
}

You even have access to the current token values themselves, if needed:

function ({ children }) {
    const { token } = useCssVarsDesignTokenContext()
    const newColor = desaturate(token.color.backgroundColor)
    return (
        <div style={{ backgroundColor: newColor }}>
            {children}
        </div>
    );
}

Benefits Over Alternative Approaches

  1. Simplicity: No build tools or preprocessors required
  2. Performance: CSS variables are highly optimized in modern browsers
  3. Developer Experience: Easy to debug using browser dev tools
  4. Framework Agnostic: The underlying CSS variables work everywhere
  5. Progressive Enhancement: Falls back gracefully if JavaScript fails

Getting Started

Install the package:

npm install css-vars-design-token

The library weighs less than 1KB gzipped and has zero dependencies beyond React.

Check out the GitHub repository for more examples and documentation.