Bootstrap 5 ships with two distinct theming systems that often get conflated: SCSS variables compiled at build time, and CSS custom properties (also called CSS variables) resolved at runtime by the browser. Choosing between them — or combining both — has real consequences for build complexity, runtime flexibility, and browser support. This post gives you an honest, side-by-side breakdown so you can make the right call for your next project.
Key Takeaways
- SCSS variables are resolved during compilation and produce zero runtime overhead; CSS custom properties are resolved by the browser and can be changed dynamically without a rebuild.
- Bootstrap 5.3 introduced a dual-layer system: it maps its own SCSS variables to CSS custom properties on
:root, giving you compile-time defaults plus runtime overrides. - CSS custom properties are supported in all modern browsers but are absent in IE 11 — a non-issue for most projects in 2025 but worth checking against your analytics.
- For static themes with a fixed palette, SCSS-only theming produces smaller, faster CSS. For multi-theme UIs or dark-mode toggling, CSS custom properties are the practical choice.
- The Canvas HTML Template uses a CSS variable called
--cnvs-themecolorso you can retheme an entire 50+ demo site by changing a single value in plain CSS.
How Bootstrap 5 Uses SCSS Variables
Bootstrap 5’s source is written in SCSS. Every spacing unit, color, border radius, and font size starts life as an SCSS variable inside _variables.scss. When you run your Sass compiler — sass --style=compressed scss/bootstrap.scss dist/bootstrap.min.css — those variables are interpolated and the resulting values are written directly into the output CSS as literal strings.
// Override in your own _custom-variables.scss before importing Bootstrap
$primary: #6d4aff;
$font-size-base: 1rem;
$border-radius: 0.5rem;
@import "bootstrap/scss/bootstrap";
The output rule will contain background-color: #6d4aff — a hard-coded hex. There is no variable in the browser’s memory. This means:
- You cannot change the value at runtime without regenerating the stylesheet.
- The browser parses static values, which is marginally faster than resolving custom properties.
- Unused variable definitions add nothing to the output file size.
SCSS variables are the right tool when your palette is fixed, your build pipeline already runs Sass, and you want the smallest possible CSS output.

How CSS Custom Properties Work in Bootstrap 5
CSS custom properties are declared with a double-hyphen prefix (--name: value) and consumed with var(--name). They are part of the cascade: you can override them on any element, including :root, a component wrapper, or even an individual element’s inline style.
:root {
--bs-primary: #6d4aff;
--bs-primary-rgb: 109, 74, 255;
}
.btn-primary {
background-color: var(--bs-primary);
}
Bootstrap 5.3 made a significant architectural move: it now declares CSS custom properties derived from its SCSS variables. So $primary compiles and also populates --bs-primary on :root. This dual-layer approach means Bootstrap’s compiled CSS already contains custom properties you can override at runtime without touching the Sass source.
Dark mode in Bootstrap 5.3 works entirely through this mechanism — a data-bs-theme="dark" attribute on <html> triggers a cascade of custom property overrides with no JavaScript recompilation needed.
SCSS vs CSS Variables: Direct Comparison
The table below covers the dimensions that matter most in production decisions:
- Runtime mutability: CSS custom properties win outright. JavaScript can write
document.documentElement.style.setProperty('--bs-primary', '#ff6b6b')and every element using that variable updates instantly. SCSS variables require a full rebuild. - Performance: SCSS variables produce static values; no variable resolution work happens in the browser. Custom properties add a tiny per-paint resolution step — negligible for most UIs but measurable if you have thousands of DOM nodes with complex property chains.
- Specificity and scope: CSS custom properties follow the cascade, so you can scope a theme to a single component without global side effects. SCSS variables are global by default (though SCSS modules help).
- Tooling dependency: SCSS requires a build step. CSS custom properties work in a plain
.cssfile, in a<style>tag, and in inline styles — zero tooling required. - Browser support: All evergreen browsers support CSS custom properties. IE 11 does not. If your analytics show any IE 11 traffic, SCSS-only output is the safe fallback.
- Developer experience: SCSS variables catch typos at compile time. CSS custom property mismatches fail silently — the browser applies the initial value and moves on.

When to Use Each Approach
Use SCSS variables alone when: the project has a single fixed brand, the build pipeline already runs Sass, IE 11 support is required, or you want maximum control over output file size. A marketing site for a single company with one brand colour is a classic example.
Use CSS custom properties alone when: you are working without a build step (prototyping, CMS-injected snippets, static HTML templates), you need dynamic theming from a colour picker or user preference, or you are adding dark mode to an existing compiled stylesheet. If you are shipping faster with HTML templates — as covered in The Front-End Developer’s Guide to Shipping Faster with HTML Templates — dropping straight into a pre-compiled template and tweaking custom properties in a separate custom.css file is often the pragmatic path.
Use both (Bootstrap 5.3’s default architecture) when: you need compile-time guarantees for your base theme but runtime flexibility for user-selectable themes, dark mode, or white-label products. This is the approach Canvas uses — SCSS sets the structure, and --cnvs-themecolor provides a clean override hook without touching source files.
Theming Canvas With CSS Custom Properties
The Canvas HTML Template exposes --cnvs-themecolor as its primary brand-colour hook. Because Canvas ships pre-compiled, you do not need a Sass build to retheme it. Create a custom.css file loaded after plugins.min.js and functions.bundle.js and write:
:root {
--cnvs-themecolor: #6d4aff;
--cnvs-themecolor-rgb: 109, 74, 255;
}
Every button, accent, link, and highlight that references --cnvs-themecolor updates across all 50+ demos instantly. For a SaaS product with multiple plan tiers or white-label clients, you can scope the variable to a wrapper element:
.client-acme {
--cnvs-themecolor: #e63946;
}
.client-beta {
--cnvs-themecolor: #2ec4b6;
}
This pattern is discussed in more depth in the context of layout composition in the Canvas SaaS Landing Demo Explained Section by Section post, where component-level theming becomes especially useful.
If you need to go deeper — overriding Bootstrap’s own --bs-primary alongside --cnvs-themecolor for full component coverage — add:
:root {
--bs-primary: #6d4aff;
--bs-primary-rgb: 109, 74, 255;
--bs-link-color: #6d4aff;
--cnvs-themecolor: #6d4aff;
--cnvs-themecolor-rgb: 109, 74, 255;
}
No rebuild. No Sass compiler. Deploy to Netlify and you are live — a workflow covered step by step in How to Deploy a Bootstrap 5 HTML Template to Netlify in 5 Minutes.
Common Mistakes to Avoid
- Mixing SCSS variable overrides with custom property overrides on the same property without understanding the order of resolution. The SCSS-compiled value is the fallback; the custom property wins if it resolves correctly. If it does not (typo, wrong scope), the compiled fallback silently applies.
- Using
var()inside SCSScalc()without understanding limitations. Sass 1.x will compilecalc(#{$spacing} + var(--offset))correctly, but older Sass versions may throw warnings. - Declaring custom properties inside a media query expecting them to work as global overrides. Custom properties in media queries are valid but scoped to the elements matched — they do not reassign the
:rootvariable globally the way you might expect. - Forgetting the RGB triplet companion variable. Bootstrap uses
--bs-primary-rgbalongside--bs-primaryso it can constructrgba()values (rgba(var(--bs-primary-rgb), 0.15)). If you override only the hex variable, transparent tints will not follow.
Frequently Asked Questions
Yes. Bootstrap 5’s distributed compiled CSS already contains --bs-* custom properties on :root. You can override them in a plain .css file loaded after the Bootstrap stylesheet. No Sass compiler or Node.js toolchain is required for runtime theming.
It uses CSS custom properties exclusively. When you add data-bs-theme="dark" to the <html> element, Bootstrap applies a set of --bs-* overrides defined in a [data-bs-theme="dark"] selector block. No recompilation occurs.
SCSS-only theming produces smaller output because variable names are not present in the compiled CSS — only their resolved values. CSS custom properties remain in the stylesheet as property declarations and their var() references, which adds bytes. For most projects the difference is negligible (typically a few kilobytes), but it is a real difference.
No. SCSS variables do not exist in the browser. Once compiled, their values are static strings in the CSS file. JavaScript can only modify CSS custom properties, inline styles, or class names. If you need runtime colour changes driven by JavaScript, CSS custom properties are the only native CSS solution.
--bs-primary is Bootstrap’s own custom property used by Bootstrap components such as buttons, badges, and alerts. --cnvs-themecolor is Canvas’s layer on top, used by Canvas-specific components and section accents. For a complete rebrand of a Canvas project, you should override both so Bootstrap components and Canvas components stay in sync.
Looking for a production-ready Bootstrap 5 HTML template? Browse Canvas Template demos and find the perfect starting point for your next project.
If you’re building with the Canvas HTML Template and want to ship production-ready Bootstrap 5 layouts faster, try Canvas Builder free — the visual builder that exports clean Canvas-ready markup in minutes.
Skip the setup — build it free
Spin up a complete Bootstrap 5 site, blog included, with Canvas Builder. No coding, no cost.
Canvas Team
Tutorials and tips for building beautiful Bootstrap 5 websites with the Canvas HTML Template and Canvas Builder.
More from the Canvas Blog