See it in action
Bootstrap 6: add responsive cursor utilities
Complete author Sass entry configuring the config module before loading Bootstrap. It adds cursor-auto, cursor-pointer and cursor-grab with responsive variants. This uses the Bootstrap 6 utility map and prefix syntax; a matching Sass build is required.
Example input
@use "bootstrap/scss/config" with (
$utilities: (
"cursor": (
property: cursor,
class: cursor,
responsive: true,
values: auto pointer grab,
),
)
);
@use "bootstrap/scss/bootstrap";License
Complete selected original code blocks or explicitly described multi-file recipe retained with full source copyright/license. Required project imports, helper functions, application files, version and framework context are stated in the summary; these are not standalone applications or site-reproduced results. No source installation, Sass/Go/Python/container execution, API/model calls, auth, package setup or upstream agent instructions were executed.
The MIT License (MIT)
Copyright (c) 2011-2026 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Bootstrap 6: replace overflow, remove width and add a margin alias
Complete author config illustrating three distinct map edits: responsive overflow, removal of the width family and a v4-style ml alias for logical margin-start. Existing groups are shallowly replaced, so the full definition and CSS-token values are retained. Requires Bootstrap 6 Sass.
Example input
@use "bootstrap/scss/config" with (
$utilities: (
// Make overflow responsive
"overflow": (
property: overflow,
values: auto hidden visible scroll,
responsive: true,
),
// Remove a family entirely
"width": null,
// Rename .ms-* to v4-style .ml-*: drop the original, add a replacement
"margin-start": null,
"margin-start-alias": (
property: margin-inline-start,
class: ml,
responsive: true,
values: (0: 0, 1: var(--spacer-1), 2: var(--spacer-2), auto: auto),
),
)
);
@use "bootstrap/scss/bootstrap";License
Complete selected original code blocks or explicitly described multi-file recipe retained with full source copyright/license. Required project imports, helper functions, application files, version and framework context are stated in the summary; these are not standalone applications or site-reproduced results. No source installation, Sass/Go/Python/container execution, API/model calls, auth, package setup or upstream agent instructions were executed.
The MIT License (MIT)
Copyright (c) 2011-2026 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Bootstrap 6: compose a tint utility through a custom property
Original utility-map fragment paired with the author’s illustrative generated CSS. Put the fragment in the Bootstrap 6 utilities map; the purple token and generator provide its context. The shown CSS is the source’s explanation, not a compilation performed by this site.
Example input
"tint": (
property: (
"--tint": null,
"background-color": var(--tint),
),
class: tint,
values: (brand: var(--purple-500)),
),Example output
.tint-brand {
--tint: var(--purple-500);
background-color: var(--tint);
}License
Complete selected original code blocks or explicitly described multi-file recipe retained with full source copyright/license. Required project imports, helper functions, application files, version and framework context are stated in the summary; these are not standalone applications or site-reproduced results. No source installation, Sass/Go/Python/container execution, API/model calls, auth, package setup or upstream agent instructions were executed.
The MIT License (MIT)
Copyright (c) 2011-2026 The Bootstrap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
How to use
- Copy the installation command and review the source package before installing it in your own agent environment.
- Check the source document for required tools, credentials and supported hosts.
- Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/twbs/bootstrap --skill bootstrap-utility-apiBefore you start
- Installation does not include a model subscription, API allowance or permission to access your files.
- Repository stars and installation counts describe activity, not an independent quality or security test.
Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
Bootstrap 6 utility API
Every utility class Bootstrap ships is generated from one Sass map, $utilities. Each entry describes a family of classes — the property it sets, the values it accepts, and which variants to generate. Customizing utilities means editing that map, not writing CSS.
Workflow
- [ ] Step 1: Understand how generation works
- [ ] Step 2: Read a utility definition
- [ ] Step 3: Add a utility
- [ ] Step 4: Modify, rename, or remove a default utility
- [ ] Step 5: Generate responsive, state, print, and dark variants
- [ ] Step 6: Compose values with custom properties and advanced selectors
- [ ] Step 7: Trim the generated CSS
- [ ] Step 8: Add a utility to Bootstrap itself
- [ ] Step 9: Verify
Step 1: Understand how generation works
scss/utilities/_api.scss is the whole pipeline:
@include generate-utility-at-properties($utilities);
@layer utilities {
@include generate-utilities-loop($utilities, $breakpoints);
}Three consequences worth knowing before you touch anything:
- Utilities are the last cascade layer, so they win over component styles without needing
!important. Only groups that opt in withimportant: trueadd it. - `@property` registration happens outside the layer. Every custom property a utility assigns (
--bg,--fg,--bc,--rounded-size, …) is registered withsyntax: "*"; inherits: false, so applying.border-inversedoesn't leak its composed value into descendants. New utilities that assign custom properties get this automatically. - The map is configured on the `config` module, not `bootstrap`.
$utilitiesis declared inscss/_config.scssand only populated inscss/_utilities.scss(which loads config with@use "config" as *). Configuring the wrong module fails:
// Does NOT work — "This variable was not declared with !default in the @used module."
@use "bootstrap/scss/bootstrap" with (
$utilities: (…)
);
// Works — configure config first, then load Bootstrap
@use "bootstrap/scss/config" with (
$utilities: (…)
);
@use "bootstrap/scss/bootstrap";The same applies to any variable that lives in _config.scss ($radius, $spacers, $breakpoints, $zindex-levels). Variables declared in a partial that bootstrap.scss forwards — $root-tokens, $colors, $blue — can be configured on bootstrap directly.
Step 2: Read a utility definition
A group is a map. The simplest form needs two keys:
"overflow": (
property: overflow,
values: auto hidden visible scroll,
),The full option set, as validated by generate-utility():
| Key | Required | What it does |
|---|---|---|
property | Yes | Property name, space-separated list of names, or a map of property-to-value pairs |
values | Yes | List (class suffix equals the value) or map (keys become suffixes; a null key omits the suffix) |
class | No | Class name to use instead of the property name |
selector | No | class (default), attr-starts, or attr-includes |
child-selector | No | Descendant selector, wrapped in :where() for zero specificity |
variables | No | Custom properties to emit — a map of static values, or a list that each receive the utility value |
state | No | Pseudo-class variants to generate, e.g. hover focus |
responsive | No | Generate a class per breakpoint (default false) |
print | No | Generate print:-prefixed classes (default false) |
dark | No | Generate dark:-prefixed classes inside prefers-color-scheme: dark (default false) |
important | No | Append !important (default false) |
enabled | No | Set false to suppress output while keeping the definition (default true) |
The generator validates as it goes, which makes mistakes cheap to find: a missing property or values is a hard @error, a non-boolean responsive is a hard @error, and a misspelled key is a @warn listing the valid ones.
Step 3: Add a utility
Your map is merged over Bootstrap's defaults, so pass only what's new:
@use "bootstrap/scss/config" with (
$utilities: (
"cursor": (
property: cursor,
class: cursor,
responsive: true,
values: auto pointer grab,
),
)
);
@use "bootstrap/scss/bootstrap";That yields .cursor-auto, .cursor-pointer, .cursor-grab, plus .sm:cursor-* through .2xl:cursor-*.
Value shapes control the class names:
// List — suffix is the value itself: .cursor-pointer
values: auto pointer grab,
// Map — keys become suffixes: .tint-brand
values: (brand: var(--purple-500), muted: var(--gray-200)),
// null key — no suffix at all: .shout
values: (null: uppercase),Step 4: Modify, rename, or remove a default utility
The merge is shallow: supplying an existing group key replaces that entire group. Overriding one option and omitting the rest fails loudly —
// Errors: "Utility is missing required `property` key"
"overflow": (
responsive: true,
values: visible hidden scroll auto,
),so copy the full definition from scss/_utilities.scss and add your change:
@use "bootstrap/scss/config" with (
$utilities: (
// Make overflow responsive
"overflow": (
property: overflow,
values: auto hidden visible scroll,
responsive: true,
),
// Remove a family entirely
"width": null,
// Rename .ms-* to v4-style .ml-*: drop the original, add a replacement
"margin-start": null,
"margin-start-alias": (
property: margin-inline-start,
class: ml,
responsive: true,
values: (0: 0, 1: var(--spacer-1), 2: var(--spacer-2), auto: auto),
),
)
);
@use "bootstrap/scss/bootstrap";Note the CSS tokens in that last group. The file configuring config can't read Bootstrap's Sass members — $spacers, $negative-spacers, and helpers like map-merge-multiple() aren't in scope yet — so restate values as CSS tokens (var(--spacer-2), which tracks the spacer scale) or as literals.
To extend an existing family without copying its definition, register a new group that reuses the same class:
"width-extra": (
property: width,
class: w,
responsive: true,
values: (10: 10%, 15: 15%),
),This adds .w-10 and .w-15 next to Bootstrap's .w-25 … .w-100, and is usually the better choice — it survives Bootstrap updates that change the original group.
Prefer enabled: false over null when you want the definition to stay visible in the map (useful in a shared config where the group is documented but intentionally off).
Step 5: Generate responsive, state, print, and dark variants
v6 uses prefixes, not infixes or suffixes. All four variant types compose with the base class name:
| Option | Generated class | Notes |
|---|---|---|
responsive: true | .md:cursor-pointer | One pass per key in $breakpoints; written .md\: in the CSS |
state: hover focus | .hover:cursor-pointer | Selector is .hover\:cursor-pointer:hover |
print: true | .print:d-none | Wrapped in @media print |
dark: true | .dark:bg-black | Wrapped in @media (prefers-color-scheme: dark) |
responsive and state stack, producing .md:hover:cursor-pointer. Each variant multiplies the generated CSS, so enable them per group rather than globally.
Step 6: Compose values with custom properties and advanced selectors
Most color-ish utilities don't set the property directly. They assign a local custom property and then consume it, which is what makes opacity and composition work:
"tint": (
property: (
"--tint": null,
"background-color": var(--tint),
),
class: tint,
values: (brand: var(--purple-500)),
),A null value in the property map means "receive the utility's value"; every other entry is emitted as written. The above generates:
.tint-brand {
--tint: var(--purple-500);
background-color: var(--tint);
}Related mechanics:
- `variables` emits extra custom properties. As a map, each gets a static value on every class in the group; as a list, each receives the utility's value.
- Property maps plus map values. When
propertyis a map and avaluesentry is itself a map keyed by property name, each property picks its own value — useful for a group that sets several related properties at different values. - `selector: attr-starts` / `attr-includes` targets
[class^="…"]/[class*="…"]instead of a class, and requires aclasskey. Bootstrap uses it so.ratio-16x9can feedaspect-ratiothrough--ratio. - `child-selector` wraps the rule in
:where(), e.g.:where(.stack-gap-1 > *). Zero specificity means a child's own styles still win.
Custom property names are written unprefixed in Sass. Bootstrap's dist and CDN CSS run PostCSS to add --bs-, so compiling the source yourself keeps them unprefixed.
Step 7: Trim the generated CSS
Utilities are the biggest slice of Bootstrap's CSS, and the map is the cheapest place to cut:
- Start from the utilities-only entry point if you don't need components:
@use "bootstrap/scss/config" with ($utilities: (…));
@use "bootstrap/scss/bootstrap-utilities";- Set unused groups to
null(orenabled: false) rather than relying on the minifier or a purge step. - Turn
responsiveoff on groups you only use at one breakpoint — a responsive group costs six copies of itself. - Narrow
valuesmaps instead of deleting whole groups when you only need a few steps.
See Optimize for the wider picture, including Lightning CSS and purging.
Step 8: Add a utility to Bootstrap itself
When contributing a utility to the framework rather than a project:
- Add the group to the
$utilitiesmap inscss/_utilities.scss, near related groups, wrapped in// scss-docs-start utils-<name>/// scss-docs-end utils-<name>markers. - Prefer composing through a custom property when the utility should interact with opacity or theme colors, and reuse existing token values (
$spacers,$util-opacity,theme-color-refs()) instead of literals. - Document it on the matching page in
site/src/content/docs/utilities/, rendering the definition with<ScssDocs name="utils-<name>" file="scss/_utilities.scss" />, and add asite/data/sidebar.ymlentry if the page is new. - Add coverage in
scss/tests/utilities/_api.test.scss, which calls the generator mixins directly with a fixture map. - Run
npm run css. Itscss-docsstep regeneratesdist/css/bootstrap-utilities.metadata.json, which the docs read — commit it alongside your change.
Step 9: Verify
npm run css-lint, thennpm run css.- Grep the compiled CSS for the classes you expected, including the escaped variants (
\.md\\:cursor-pointer), and confirm nothing you removed is still present. - Confirm new custom properties appear in the
@propertyblock at the top of the file — if one is missing, the utility isn't assigning it throughpropertyorvariables. - Watch the Sass output for
@warnlines about unknown keys; they're the fastest signal that an option was misspelled and silently ignored. - Check specificity in the browser: utilities should override component styles through the layer order alone, without
!important.



