Bootstrap 5 theming: Sass variables vs CSS custom properties precedence
0 reputation · 30 Aug 2022, 01:42 UTC
0 reputation · 30 Aug 2022, 01:42 UTC
The goal is to determine which theming mechanism—Sass variables defined at build time or CSS custom properties set at runtime—takes effect when both are present for the same theme token (e.g., --bs-primary).
Bootstrap 5 compiles Sass variables into static CSS values, yet also exposes CSS custom properties for many tokens. Documentation does not clarify whether a custom property overrides the compiled Sass‑derived value, or whether the Sass value remains authoritative, leading to inconsistent behavior when developers attempt runtime theme changes without recompiling.
What happens when a custom property and its corresponding Sass variable are both defined?
How can developers guarantee consistent runtime theme overrides across all Bootstrap components without recompiling the source?
Is there a documented approach to force Bootstrap to rely exclusively on CSS custom properties for theme values?
30775 reputation · 30 Aug 2022, 04:56 UTC
1. What happens when a custom property and its corresponding Sass variable are both defined?
When Bootstrap’s compiled CSS uses var(--bs‑primary) (which is the case for most tokens in 5.3+), the runtime value of the custom property overrides the static value that was baked in by Sass. The cascade resolves var() at the time the rule is applied, so the custom property wins if it is defined on a selector that is at least as specific as the rule that uses it.
In contrast, if the CSS rule contains a hard‑coded value (e.g., #0d6efd instead of var(--bs‑primary)), the Sass‑derived value remains authoritative and cannot be overridden by setting the custom property.
2. How can developers guarantee consistent runtime theme overrides across all Bootstrap components without recompiling the source?
1. Identify the token you want to override (commonly --bs‑primary, --bs‑secondary, etc.).
2. After Bootstrap’s JavaScript has initialized, set the property on :root via CSS or JavaScript:
document.documentElement.style.setProperty('--bs-primary', '#ff5722');
3. Verify that the component’s CSS uses var(--bs‑primary) by inspecting the computed style. If the rule is hard‑coded, you must write a supplemental rule that targets the component and sets the property with higher specificity or !important.
4. Repeat for any other tokens you wish to change.
3. Is there a documented approach to force Bootstrap to rely exclusively on CSS custom properties for theme values?
Bootstrap does not provide a switch to replace all hard‑coded values with var(). The framework’s Sass layer is still required for build‑time logic (e.g., generating utilities, responsive breakpoints). However, you can achieve a near‑exclusive runtime approach by:
:root stylesheet that sets every exposed token to the desired value.In short, you can rely on CSS custom properties for most runtime theming, but you cannot eliminate the Sass layer entirely without rebuilding Bootstrap.
Bootstrap’s Sass variables (e.g., $primary) are compiled into static CSS values. When the compiled stylesheet contains var(--bs‑primary), the custom property value is resolved at runtime. If the custom property is defined after the stylesheet loads, its value overrides the static value for all rules that reference it. If a rule contains a hard‑coded value, the static value is final and cannot be overridden by the custom property.
Because the cascade applies the most specific rule that matches, setting the custom property on :root is usually sufficient. If you encounter components that still use the old color, check whether their CSS has a more specific selector or a hard‑coded value.
Do you know whether your project uses Bootstrap 5.3 or newer? Earlier releases expose fewer tokens as custom properties, which may require additional manual overrides.
Use comments to ask for clarification. Post a solution as an answer.
30,775 reputation · 30 Aug 2022, 02:35 UTC
Bootstrap’s compiled styles often write a token as var(--bs‑primary, #0d6efd). The first argument is the custom property; the second is a hard‑coded fallback that matches the original Sass value. If --bs‑primary is defined on :root (or any ancestor), the var() call resolves to that value and the fallback is ignored. If the property is missing, the fallback keeps the component’s original color. This pattern lets developers change the theme at runtime while still guaranteeing a sensible default when the custom property is not set.
Because the fallback is part of the CSS rule, you can also target a narrower scope—e.g., setting --bs‑primary on a .dark‑theme container—to override the token only for that section.