Skip to main content Skip to docs navigation

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 colorDefault valueDescription
primaryLoading...Loading... var(--bs-blue-500)Main brand color for primary actions
accentLoading...Loading... var(--bs-indigo-500)Complementary brand color option
successLoading...Loading... var(--bs-green-500)Positive actions and successful states
dangerLoading...Loading... var(--bs-red-500)Destructive actions and error states
warningLoading...Loading... var(--bs-yellow-500)Cautionary messages and states
infoLoading...Loading... var(--bs-cyan-500)Informational messages and neutral states
inverseLoading...Loading... var(--bs-gray-900)High contrast by inverting foreground and background
secondaryLoading...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 tokenDescription
baseThe default color value for the semantic color
textAccessible text color (against body, plus subtle and muted color tokens)
text-emphasisEmphasized text color for use with muted background tokens
bgFor solid colored backgrounds with high contrast
bg-subtleLowest contrast backgrounds, usually paired with text key for text color
bg-mutedLower contrast backgrounds, often used for disabled states
borderBorders and dividers
focus-ringFor visible focus indicators and outline styles
contrastText 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
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast
Accent
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast
Success
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast
Danger
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast
Warning
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast
Info
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast
Inverse
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast
Secondary
base
text
text-emphasis
bg
bg-subtle
bg-muted
border
focus-ring
contrast

Pairings

Not all colors can be used for all purposes due to accessibility, color contrast, and general aesthetic considerations. Here are some recommended pairings.

  • contrast work best with bg
  • text works best with subtle
  • text-emphasis works best with muted
  • border works best with subtle, but can be used with muted
Example element with theme color
Example element with theme color
Example element with theme color
HTML
<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.

BackgroundDefault valueDescription
bodyLoading...Loading...Default background color
secondaryLoading...Loading...Lowest contrast background color
subtleLoading...Loading...Lower contrast background color
mutedLoading...Loading...Medium contrast background color, typically used for disabled states
whiteLoading...Loading...Pure white background color
blackLoading...Loading...Pure black background color
transparentLoading...Loading...Transparent background color
inheritinheritInherited background color

Foreground

Almost all those options are also available for foreground text colors.

ForegroundDefault valueDescription
bodyLoading...Loading...Default foreground color
secondaryLoading...Loading...Lowest contrast foreground color
subtleLoading...Loading...Lower contrast foreground color
mutedLoading...Loading...Medium contrast foreground color
whiteLoading...Loading...Pure white foreground color
blackLoading...Loading...Pure black foreground color
inheritinheritInherited foreground color

Border

Border colors have similar levels, but different naming.

BorderDefault valueDescription
nullLoading...Loading...Default border color
mutedLoading...Loading...Muted border color
subtleLoading...Loading...Subtle border color
emphasizedLoading...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-body works with all bg colors
  • fg-1 works with bg-body, bg-1, bg-2, and bg-3
  • fg-2 works with bg-body, bg-1, and bg-2
  • fg-3 works with bg-body, bg-1

Here are some examples showing them together. Note

fg-body on bg-body
fg-3 on bg-1
fg-2 on bg-2
fg-1 on bg-3
HTML
<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.

Primary alert
Primary badge Primary subtle badge
HTML
<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.

Primary alert
Primary badge Primary subtle badge
HTML
<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.

Primary alert
Success badge Primary subtle badge
HTML
<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.

SCSS
$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.

SCSS
--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};
}