Theme Bulma Without Forking It: Overriding CSS Custom Properties the Maintainable Way
Stop duplicating selectors to restyle Bulma components. Learn how to override the framework's exposed CSS custom properties from a single :root block while keeping the cascade predictable.
07 Apr 2026, 14:27 UTC

The duplicated-selector trap
When a designer asks to shift Bulma's primary color from blue to teal, the reflex is often to open a custom stylesheet and start writing rules like .button.is-primary, .navbar-item, and .card-header-title. Within an hour you have a parallel stylesheet that duplicates Bulma's own logic, and every future component update risks visual drift because a new selector was missed.
Bulma's exposed custom properties
Bulma defines a set of CSS custom properties (often called CSS variables) in its :root block. These tokens—such as --primary, --secondary, --grey-dark, and --grey-light—act as single sources of truth. Because they are standard custom properties, they participate in the normal CSS cascade. Changing a value at the root level updates every component that references that token, without touching Bulma's compiled selectors.
Before relying on a specific token, verify it exists in your installed version. You can inspect the stylesheet directly:
# Run from your project root in a terminal
grep -n ':root' node_modules/bulma/css/bulma.css | head -5
Expected check: the output should show the line number of the :root block. If you are using the minified build, the entire file may be on one line, so browser devtools are a faster way to confirm the available properties.
A worked teal theme
Suppose the design team wants a teal palette. Instead of hunting selectors, create a small override file:
/* theme.css */
:root {
--primary: #009688;
--secondary: #00bfa5;
}
Load it after Bulma so source order favors your values:
<link rel="stylesheet" href="/css/bulma.min.css">
<link rel="stylesheet" href="/css/theme.css">
With equal specificity, the later :root rule wins. Buttons, navbars, cards, and form controls that reference --primary will adopt the new teal immediately.
If your build pipeline forces Bulma to load last, raise specificity instead:
:root:root {
--primary: #009688;
--secondary: #00bfa5;
}
The doubled pseudo-class increases specificity enough to win regardless of order.
How to verify the change took effect
Open browser devtools, inspect any Bulma button with the class is-primary, and look at the computed background-color. It should resolve to #009688 (or the RGB equivalent). If the old color persists, check the Styles panel to confirm your theme.css is actually loaded and that no other :root rule appears after it.
What custom properties do not solve
This approach is powerful but bounded. Only the variables Bulma explicitly exposes are customizable. If you need to scale border-radius globally, adjust complex component layouts, or restyle states that Bulma hardcodes rather than tokenizes, you will still need manual CSS or Sass overrides.
Browser support is the other limitation. CSS custom properties are unsupported in Internet Explorer 11. If your project must serve IE11, plan a static fallback stylesheet that sets explicit colors on the affected components, or use a polyfill. Modern evergreen browsers handle the cascade natively.
Actionable next steps
- Inspect your installed
bulma.cssand list the custom properties available in the:rootblock. - Create a
theme.cssthat overrides only the tokens your brand requires. - Load it after Bulma (or use
:root:rootif order is fixed) and verify one component in devtools. - Document which tokens are overridden so future developers know where the theme lives.
By treating Bulma's custom properties as your theming API, you keep the framework's structural benefits while eliminating the brittle duplicate-selector stylesheet that becomes impossible to maintain.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.