Runtime Theming with Carbon Design System Using CSS Custom Properties
Learn how to change Carbon Design System themes at runtime by overriding CSS custom properties, with a worked example, trade‑offs, and verification steps.
11 Jan 2026, 23:24 UTC

Problem: Changing Themes at Runtime
Many web applications need to switch color themes—light, dark, or brand‑specific—without forcing a full page reload or rebuilding the CSS bundle. When the design system is Carbon, the typical approach of swapping a stylesheet or toggling a class that changes hard‑coded values can lead to a flash of unstyled content or require JavaScript to rewrite inline styles.
Thesis: Leverage Carbon’s CSS Custom Properties
Carbon Design System already defines its color palette as CSS custom properties (e.g., --cds-global--primary). Because these properties live in the stylesheet, changing their value at the :root level updates every component that references them instantly, with no JavaScript required for the actual color swap.
How Carbon Exposes the Properties
When you include the Carbon CSS bundle (via <link> or a build step), the stylesheet contains rules like:
:root {
--cds-global--primary: #0069d9;
--cds-global--background: #ffffff;
/* … many more tokens … */
}
Components such as bx--btn or bx--form-field reference these tokens via var(--cds-global--primary). Therefore, overriding a custom property propagates through the entire component tree.
Enabling Light/Dark Mode with a Single Class
Carbon provides a theme class (--cds-theme--dark) that, when added to the html element, switches the values of a second set of custom properties defined for dark mode. The CSS looks roughly like:
html.--cds-theme--dark {
--cds-global--primary: #339fff;
--cds-global--background: #0a0a0a;
/* … dark overrides … */
}
Toggling this class changes all dependent variables at once, keeping the theming logic minimal.
Worked Example: Switching Themes at Runtime
- Add the Carbon CSS bundle to your page:
- Create a simple UI with a button and a toggle:
- Add a small script that toggles the dark‑mode class on the
htmlelement (this script only manages the class; the actual color change is handled by CSS): - Open the page in a browser, click the button, and observe the button’s background and text color change instantly without a reload.
<link rel="stylesheet" href="https://unpkg.com/@carbon/themes@latest/css/themes.css">
<link rel="stylesheet" href="https://unpkg.com/carbon-components@latest/css/carbon-components.css">
<button class="bx--btn bx--btn--primary" id="themeBtn"
>Switch Theme</button>
document.getElementById('themeBtn').addEventListener('click', function () {
document.documentElement.classList.toggle('--cds-theme--dark');
});
You can verify the mechanism in DevTools:
- Inspect the
htmlelement and see the--cds-theme--darkclass appear/disappear. - Check the computed style of a Carbon button; the
background-colorwill show a value likergb(51, 153, 255)(dark mode) orrgb(0, 105, 217)(light mode), confirming it comes from the custom property. - Toggle the class manually in the Elements panel and watch the colors update in real time.
Trade‑offs and Limitations
While this approach is powerful, consider the following:
- Browser support: CSS custom properties are not available in Internet Explorer 11 or very old Safari versions; those browsers will fall back to the default values defined in the stylesheet.
- Component overrides: If a component locally sets its own
--cds-global--primary(e.g., via inline style or a scoped class), the global theme change will not affect it unless the component is written to inherit the variable. - Performance: Rapidly changing many custom properties can trigger layout reflows. Batch changes (e.g., using
requestAnimationFrame) or limit updates to user‑initiated actions to avoid hiccups.
Actionable Closing
To adopt runtime theming with Carbon:
- Include the Carbon CSS bundle in your project.
- Identify the root‑level custom properties you wish to modify (start with the primary and background tokens).
- Set or toggle those properties via JavaScript (or a class that defines dark‑mode overrides) at the
:rootorhtmllevel. - Test in the browsers you support, checking both computed styles and visual output.
- Monitor for any components that override the variables and adjust them to use the inherited custom property if dynamic theming is required.
By relying on Carbon’s built‑in CSS custom properties, you achieve instant, JavaScript‑light theming that works even in environments where script execution is delayed or restricted.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.