Extending Bootstrap 5 with Custom Utilities via the Utility API
Learn how to extend Bootstrap 5 with custom utility classes using the Utility API, including a responsive brand background example, trade-offs, and verification steps.
14 Dec 2025, 07:28 UTC

Problem: design-system gaps that force ad-hoc CSS
Teams using Bootstrap 5 often need a spacing value outside the default $spacer scale or a brand-specific color utility. Writing one-off classes misses Bootstrap's responsive infix system, state variants, and compile-time pruning. The result is inconsistency and harder maintenance.
Thesis: the Utility API lets you declare utilities as data in Sass and get responsive, state and CSS-variable support automatically
Bootstrap 5.0 introduced the Utility API. Utilities are defined in the $utilities Sass map. Each entry describes property, values, class prefix, responsive flag, state variants and optional css-var output. Because generation happens at compile time, only the utilities you configure are emitted.
How the map drives generation
An entry is a Sass map with keys such as property, values, class, responsive, state and css-var. Property sets the CSS property to output. Values is a map of modifier to value. Class is the prefix used for the class name. Responsive true adds breakpoint infixes like -sm, -md. State lists pseudo-classes such as hover or focus. Css-var true emits a CSS custom property for runtime theming.
The API respects $enable-negative-margins and $enable-negative-padding toggles, and spacing utilities stay aligned to $spacer.
Worked example: a brand background utility with responsive and hover variants
Assume a project needs .bg-brand-100 that uses a brand color and should be available at breakpoints with a hover variant.
Create a Sass entry point, for example src/scss/app.scss, in the project source folder. You need write permission to the source folder and read permission to node_modules/bootstrap.
@use "sass:map";
@use "bootstrap/scss/functions";
@use "bootstrap/scss/variables" as *;
// Define custom values
$brand-colors: (
"brand-100": #eef6ff
);
// Extend the utilities map before using utilities
$utilities: map.merge(
map.get(variables.$utilities, "background-color"),
(
property: background-color,
class: bg,
values: map.merge(map.get(variables.$utilities, "background-color").values, $brand-colors),
responsive: true,
state: hover focus,
css-var: false
)
);
@use "bootstrap/scss/utilities" with (
$utilities: $utilities
);
Compile with Dart Sass from the project root:
sass src/scss/app.scss dist/css/app.css --style=expandedExpected checks after compile: open dist/css/app.css and search for .bg-brand-100. Verify the class exists and that responsive infixes such as .bg-sm-brand-100 are present when responsive is true. Verify hover and focus variants appear when state is set. Risks: setting responsive true for many values multiplies output per breakpoint. Map merge order matters; project additions should be merged after Bootstrap defaults to avoid accidental overrides.
Trade-offs and limitations
- Bundle size grows with responsive true and state variants. Limit responsive to utilities actually needed at breakpoints.
- Custom utilities do not automatically generate RTL variants. Bootstrap's RTL pipeline handles core utilities; test custom utilities in RTL builds.
- Between Bootstrap 5.0 and 5.3 the API added state variants like active and the css-var option. Review the migration guide when upgrading.
- Negative spacing utilities are gated by $enable-negative-margins and $enable-negative-padding.
Closing: use the API for systematic extensions
Treat utilities as configuration rather than hand-written CSS. Define the values you need, control responsive and state generation explicitly, and verify the compiled output contains the expected class names. This keeps the design system consistent with Bootstrap theming while avoiding unnecessary CSS.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.