Expanding on Theming Configuration: A Comprehensive Guide for Experienced Developers

A detailed exploration of theming configuration — the backbone of design systems and reusable UI libraries. Learn how theme tokens, contexts, and component APIs pave the way for scalable and efficient styling in modern applications.

ShareShare

Expanding on Theming Configuration: A Comprehensive Guide for Advanced Developers

In the realm of advanced frontend engineering, building components that are reusable is not merely about structuring logic. It extends to making these components visually adaptable. This is precisely where the concept of theming configuration comes into play.

Theming is not merely about setting colors. It is a complex process involving design abstraction, scalability, and developer ergonomics. At its heart, a theming config acts as a structured, composable method to apply various visual styles (colors, sizes, spacings, typography, etc.) across a UI library. It also provides the ability to customize appearance without having to rewrite any logic.

In this comprehensive guide, a detailed exploration of the following points will be provided:

  • The definition of a theming config
  • The difference between tokens, values, and components
  • The structure of theme systems in tools like Chakra UI, Tailwind, and Material UI
  • Implementation patterns using React Context, CSS variables, and TypeScript
  • Real-world strategies for scalable theming across large applications

The Evolution of Theming: From Inline Styles to Design Systems

The initial days of web UIs saw styles applied in an ad hoc manner:

  • Inline styles were applied directly to tags
  • Global CSS files with hardcoded rules were common
  • There was a lack of consistency between components

However, as applications began to grow, these methods proved to be inadequate:

  • Maintaining visual consistency became a challenge
  • Customization was difficult without creating a fork
  • There was no method to theme across brands or use cases

Theming configs were introduced to address these issues. They decoupled visual styles from component logic, allowing developers to:

  • Apply global tokens across systems
  • Switch between different themes at runtime (e.g., light/dark mode)
  • Customize without modifying the internal workings of the system
  • Enable accessible, scalable branding

In today's scenario, every design system — whether it's in Figma or coded — is powered by a theme config.


Deep Dive into Theme Config

A theming config is essentially a structured object (typically in JSON or JS/TS) that defines semantic values and style primitives.

Here's an example:

const theme = {
  colors: {
    primary: "#3B82F6",
    secondary: "#64748B",
    background: "#F8FAFC",
    text: "#111827"
  },
  fontSizes: {
    sm: "12px",
    md: "16px",
    lg: "20px"
  },
  space: [0, 4, 8, 16, 32, 64],
  radii: {
    sm: "2px",
    md: "6px",
    lg: "12px"
  }
}

These values can be accessed by various means, such as:

  • Styling utilities like Tailwind and Emotion
  • Component props like <Button size="lg" />
  • Context-aware hooks
  • CSS variables injected via a provider

Tokens vs Values vs Semantics

In theming, the separation of concerns brings clarity:

| Concept | Example | Purpose | |------------|----------------|------------------------------------| | Token | primary.500 | Design value with semantic meaning | | Value | #3B82F6 | Actual CSS value | | Semantic | text.primary | Contextual usage |

This separation enables:

  • Themes to be swapped without the need to rewrite code
  • Easier adaptations for accessibility (e.g., contrast modes)
  • The possibility for brand theming and multi-tenant design

Implementing Theming with Context in React

Most component libraries wrap the application in a <ThemeProvider>:

<ThemeProvider theme={theme}>
  <App />
</ThemeProvider>

Inside components, values are consumed either via hooks or styled props:

const styles = useTheme(); // e.g. styled-components, Emotion

return <div style={{ color: styles.colors.primary }} />

React Context allows dynamic switching — for example, you can toggle dark mode at runtime:

const darkTheme = {
  colors: {
    background: "#111",
    text: "#EEE"
  }
}

Leveraging CSS Variables for Runtime Theming

For enhanced runtime performance and interoperability, many libraries use CSS variables:

:root {
  --color-primary: #3B82F6;
  --font-size-md: 16px;
}

[data-theme="dark"] {
  --color-primary: #0EA5E9;
}

These variables can be referenced in components:

button {
  color: var(--color-primary);
}

This allows runtime switching without rerendering React — an essential feature for accessibility, multi-brand apps, or white-labeling.


Theming in Established Design Systems

Chakra UI

Chakra UI uses a deeply structured theme config that includes color modes, semantic tokens, and responsive arrays:

theme.components.Button = {
  baseStyle: {
    fontWeight: "bold"
  },
  sizes: {
    md: {
      px: 4,
      py: 2,
      fontSize: "md"
    }
  }
}

Material UI

Material UI allows overriding tokens at multiple levels:

createTheme({
  palette: {
    primary: {
      main: "#1976d2"
    }
  },
  typography: {
    button: {
      textTransform: "none"
    }
  }
})

It supports ThemeProvider, sx prop, and component-level overrides.

Tailwind (via config)

Tailwind’s tailwind.config.js acts as a theme generator:

module.exports = {
  theme: {
    colors: {
      primary: "#2563EB"
    },
    fontSize: {
      sm: "0.875rem",
      base: "1rem"
    }
  }
}

Advanced Patterns

  • Theme composition: Dynamically merge base themes with brand themes
  • Media-query aware theming: For instance, prefers-color-scheme
  • Multi-brand tokens: Load theme per organization/site
  • SSR-safe hydration: Preload theme before React renders
  • Scoped themes: Change theme per section/component

Leveraging TypeScript for Theming

With TypeScript, you can enforce token correctness:

type Theme = {
  colors: Record<string, string>;
  fontSizes: { sm: string; md: string; lg: string };
};

const theme: Theme = { ... };

This prevents typos and enables IDE autocompletion, making theming safer and more efficient at scale.


Anti-Patterns

  • Hardcoding values inside components
  • Using raw hex values instead of tokens
  • Over-customizing without clearly defined theme boundaries
  • Nesting themes without a clear reset layer
  • Skipping semantic naming (blue1, blue2, blue3)

Conclusion: The Power of Theming

Theming configuration is not just about visuals — it's fundamentally architectural. It empowers your components to scale across products, brands, and use cases without sacrificing flexibility.

The survivability of design systems is largely dependent on their theme layer. As such, it's crucial to build it like a product.

By making your UI configurable by intent and not just by color, you're building more than components — you're building a platform.

Subscribe for Deep Dives

Get exclusive in-depth technical articles and insights directly to your inbox.

about

Ehsan Hosseini

Ehsan Hosseini

me [at] ehosseini [dot] info

Staff Software Engineer and Tech Lead with a track record of leading high-performing engineering teams and delivering scalable, end-to-end technology solutions. With experience across web, mobile, and backend systems, I help companies make smart architectural decisions, scale efficiently, and align technical strategy with business goals.

© 2025 Ehsan Hosseini. All rights reserved.