Theme
The Bootstrap theme is a set of semantically named colors that are used to style our components, utilities, and more. The theme is configurable, responds to color modes, and can be consumed via Sass or CSS.
How it works
Theme colors are defined in the $new-theme-colors Sass map. This map is used to generate our theme color values. You'll find these values in the _theme.scss file. These are where we define our design tokens for Bootstrap, across both light and dark color modes.
Theme colors include the following semantic colors:
| Theme color | Default value | Description |
|---|---|---|
primary | Loading...Loading... var(--bs-blue-500) | Main brand color for primary actions |
accent | Loading...Loading... var(--bs-indigo-500) | Complementary brand color option |
success | Loading...Loading... var(--bs-green-500) | Positive actions and successful states |
danger | Loading...Loading... var(--bs-red-500) | Destructive actions and error states |
warning | Loading...Loading... var(--bs-yellow-500) | Cautionary messages and states |
info | Loading...Loading... var(--bs-cyan-500) | Informational messages and neutral states |
inverse | Loading...Loading... var(--bs-gray-900) | High contrast by inverting foreground and background |
secondary | Loading...Loading... var(--bs-gray-300) | Less prominent actions and states |
And within each semantic theme color, you'll find the following keys, most of which are color-mode adaptive:
| Theme token | Description |
|---|---|
base | The default color value for the semantic color |
text | Accessible text color (against body, plus subtle and muted color tokens) |
text-emphasis | Emphasized text color for use with muted background tokens |
bg | For solid colored backgrounds with high contrast |
bg-subtle | Lowest contrast backgrounds, usually paired with text key for text color |
bg-muted | Lower contrast backgrounds, often used for disabled states |
border | Borders and dividers |
focus-ring | For visible focus indicators and outline styles |
contrast | Text color that needs to be readable on the base and bg colors |
Theme colors
Every token is available as a CSS variable, and most are then consumed by our utilities and components. So for the primary color, you have the following colors:
Primary
Accent
Success
Danger
Warning
Info
Inverse
Secondary
Pairings
Not all colors can be used for all purposes due to accessibility, color contrast, and general aesthetic considerations. Here are some recommended pairings.
contrastwork best withbgtextworks best withsubtletext-emphasisworks best withmutedborderworks best withsubtle, but can be used withmuted
<div class="theme-primary vstack gap-3">
<div style="color: var(--bs-theme-contrast); background: var(--bs-theme-bg);" class="p-3 rounded-3">
Example element with theme color
</div>
<div style="color: var(--bs-theme-text-emphasis); background: var(--bs-theme-bg-muted); border: 1px solid var(--bs-theme-border);" class="p-3 rounded-3">
Example element with theme color
</div>
<div style="color: var(--bs-theme-text); background: var(--bs-theme-bg-subtle); border: 1px solid var(--bs-theme-border);" class="p-3 rounded-3">
Example element with theme color
</div>
</div> Layer colors
Color tokens that are used for foreground, background, and border colors are called theme layer colors in Bootstrap. These layer colors are configured outside the $new-theme-colors Sass map in their own respective Sass maps as they have more nuanced theming use cases.
Tokens for these three themes are defined in the $theme-fgs, $theme-bgs, and $theme-borders Sass maps. These maps are used to generate color mode adaptive color, background-color, and border-color values that are then consumed by our utilities and components. You'll find these values in the _theme.scss file.
Background
Theme backgrounds include several practical and semantic color options.
| Background | Default value | Description |
|---|---|---|
body | Loading...Loading... | Default background color |
secondary | Loading...Loading... | Lowest contrast background color |
subtle | Loading...Loading... | Lower contrast background color |
muted | Loading...Loading... | Medium contrast background color, typically used for disabled states |
white | Loading...Loading... | Pure white background color |
black | Loading...Loading... | Pure black background color |
transparent | Loading...Loading... | Transparent background color |
inherit | inherit | Inherited background color |
Foreground
Almost all those options are also available for foreground text colors.
| Foreground | Default value | Description |
|---|---|---|
body | Loading...Loading... | Default foreground color |
secondary | Loading...Loading... | Lowest contrast foreground color |
subtle | Loading...Loading... | Lower contrast foreground color |
muted | Loading...Loading... | Medium contrast foreground color |
white | Loading...Loading... | Pure white foreground color |
black | Loading...Loading... | Pure black foreground color |
inherit | inherit | Inherited foreground color |
Border
Border colors have similar levels, but different naming.
| Border | Default value | Description |
|---|---|---|
null | Loading...Loading... | Default border color |
muted | Loading...Loading... | Muted border color |
subtle | Loading...Loading... | Subtle border color |
emphasized | Loading...Loading... | Emphasized border color |
Examples
Not all colors can be used for all purposes due to accessibility, color contrast, and general aesthetic considerations. Here are some recommended pairings.
fg-bodyworks with allbgcolorsfg-1works withbg-body,bg-1,bg-2, andbg-3fg-2works withbg-body,bg-1, andbg-2fg-3works withbg-body,bg-1
Here are some examples showing them together. Note
<div class="vstack gap-3">
<div class="p-3 rounded-3 bg-body fg-body border">
fg-body on bg-body
</div>
<div class="p-3 rounded-3 bg-1 fg-3 border">
fg-3 on bg-1
</div>
<div class="p-3 rounded-3 bg-2 fg-2 border">
fg-2 on bg-2
</div>
<div class="p-3 rounded-3 bg-3 fg-1 border">
fg-1 on bg-3
</div>
</div> Theme utility classes
We generate theme utility classes from the $new-theme-colors Sass map that make all theme color tokens available as CSS variables. We use these in our component variants to allow for quick theming with a single, global class. This requires components to support theme colors, and not every component does.
With theme utilities, you can apply a theme color to an element with a single class.
<div class="alert theme-primary">Primary alert</div>
<div>
<button type="button" class="btn btn-solid theme-primary">Primary button</button>
<button type="button" class="btn btn-outline theme-primary">Primary outline button</button>
<button type="button" class="btn btn-subtle theme-primary">Primary subtle button</button>
<button type="button" class="btn btn-text theme-primary">Primary text button</button>
</div>
<div>
<span class="badge theme-primary">Primary badge</span>
<span class="badge badge-subtle theme-primary">Primary subtle badge</span>
</div> And you can apply a theme color utility to a container and any theme-aware children will inherit the theme color.
<div class="vstack gap-3 theme-primary">
<div class="alert">Primary alert</div>
<div>
<button type="button" class="btn btn-solid">Primary button</button>
<button type="button" class="btn btn-outline">Primary outline button</button>
<button type="button" class="btn btn-subtle">Primary subtle button</button>
<button type="button" class="btn btn-text">Primary text button</button>
</div>
<div>
<span class="badge">Primary badge</span>
<span class="badge badge-subtle">Primary subtle badge</span>
</div>
</div> This also means you can override a container's theme color with another theme color on specific components.
<div class="vstack gap-3 theme-primary">
<div class="alert">Primary alert</div>
<div>
<button type="button" class="btn btn-solid theme-emphasis">Emphasis button</button>
<button type="button" class="btn btn-outline">Primary outline button</button>
<button type="button" class="btn btn-subtle theme-danger">Danger subtle button</button>
<button type="button" class="btn btn-text">Primary text button</button>
</div>
<div>
<span class="badge theme-success">Success badge</span>
<span class="badge badge-subtle">Primary subtle badge</span>
</div>
</div> Theme Sass map
We use a large, nested Sass map to generate our theme color values.
$new-theme-colors: (
"primary": (
"base": var(--blue-500),
"text": light-dark(var(--blue-600), var(--blue-400)),
"text-emphasis": light-dark(var(--blue-800), var(--blue-200)),
"bg": var(--blue-500),
"bg-subtle": light-dark(var(--blue-100), var(--blue-900)),
"bg-muted": light-dark(var(--blue-200), var(--blue-800)),
"border": light-dark(var(--blue-300), var(--blue-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--blue-500), var(--blue-400)) 50%, var(--bg-body)),
"contrast": var(--white)
),
"accent": (
"base": var(--indigo-500),
"text": light-dark(var(--indigo-600), color-mix(in oklch, var(--indigo-400), var(--indigo-300))),
"text-emphasis": light-dark(var(--indigo-800), var(--indigo-300)),
"bg": var(--indigo-500),
"bg-subtle": light-dark(var(--indigo-100), var(--indigo-900)),
"bg-muted": light-dark(var(--indigo-200), var(--indigo-800)),
"border": light-dark(var(--indigo-300), var(--indigo-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--indigo-500), var(--indigo-400)) 50%, var(--bg-body)),
"contrast": var(--white)
),
"success": (
"base": var(--green-500),
"text": light-dark(var(--green-600), var(--green-400)),
"text-emphasis": light-dark(var(--green-800), var(--green-300)),
"bg": var(--green-500),
"bg-subtle": light-dark(var(--green-100), var(--green-900)),
"bg-muted": light-dark(var(--green-200), var(--green-800)),
"border": light-dark(var(--green-300), var(--green-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--green-500), var(--green-400)) 50%, var(--bg-body)),
"contrast": var(--white)
),
"danger": (
"base": var(--red-500),
"text": light-dark(var(--red-600), var(--red-400)),
"text-emphasis": light-dark(var(--red-800), var(--red-300)),
"bg": var(--red-500),
"bg-subtle": light-dark(var(--red-100), var(--red-900)),
"bg-muted": light-dark(var(--red-200), var(--red-800)),
"border": light-dark(var(--red-300), var(--red-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--red-500), var(--red-400)) 50%, var(--bg-body)),
"contrast": var(--white)
),
"warning": (
"base": var(--yellow-500),
"text": light-dark(var(--yellow-700), var(--yellow-400)),
"text-emphasis": light-dark(var(--yellow-800), var(--yellow-300)),
"bg": var(--yellow-500),
"bg-subtle": light-dark(var(--yellow-100), var(--yellow-900)),
"bg-muted": light-dark(var(--yellow-200), var(--yellow-800)),
"border": light-dark(var(--yellow-300), var(--yellow-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--yellow-500), var(--yellow-400)) 50%, var(--bg-body)),
"contrast": var(--gray-900)
),
"info": (
"base": var(--cyan-500),
"text": light-dark(var(--cyan-600), var(--cyan-400)),
"text-emphasis": light-dark(var(--cyan-800), var(--cyan-300)),
"bg": var(--cyan-500),
"bg-subtle": light-dark(var(--cyan-100), var(--cyan-900)),
"bg-muted": light-dark(var(--cyan-200), var(--cyan-800)),
"border": light-dark(var(--cyan-300), var(--cyan-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--cyan-500), var(--cyan-400)) 50%, var(--bg-body)),
"contrast": var(--gray-900)
),
"inverse": (
"base": var(--gray-900),
"text": light-dark(var(--gray-900), var(--gray-200)),
"text-emphasis": light-dark(var(--gray-975), var(--white)),
"bg": light-dark(var(--gray-900), var(--gray-025)),
"bg-subtle": light-dark(var(--gray-100), var(--gray-900)),
"bg-muted": light-dark(var(--gray-200), var(--gray-300)),
"border": light-dark(var(--gray-400), var(--gray-100)),
"focus-ring": color-mix(in oklch, light-dark(var(--gray-900), var(--gray-100)) 50%, var(--bg-body)),
"contrast": light-dark(var(--white), var(--gray-900))
),
"secondary": (
"base": var(--gray-200),
"text": light-dark(var(--gray-600), var(--gray-400)),
"text-emphasis": light-dark(var(--gray-800), var(--gray-200)),
"bg": light-dark(var(--gray-100), var(--gray-600)),
"bg-subtle": light-dark(var(--gray-050), var(--gray-800)),
"bg-muted": light-dark(var(--gray-100), var(--gray-700)),
"border": light-dark(var(--gray-300), var(--gray-600)),
"focus-ring": color-mix(in oklch, light-dark(var(--gray-500), var(--gray-300)) 50%, var(--bg-body)),
"contrast": light-dark(var(--gray-900), var(--white))
)
);
CSS variables
CSS variables are generated from the $new-theme-colors Sass map at the :root level inside _root.scss using a Sass loop.
--black: #{$black};
--white: #{$white};
// Generate semantic theme colors
@each $color-name, $color-map in $new-theme-colors {
@each $key, $value in $color-map {
--#{$color-name}-#{$key}: #{$value};
}
}
@each $color, $value in $theme-bgs {
--bg-#{$color}: #{$value};
}
@each $color, $value in $theme-fgs {
--fg-#{$color}: #{$value};
}
@each $color, $value in $theme-borders {
--border-#{$color}: #{$value};
}