Shadows

Add or remove shadows to elements with box-shadow utilities.

ClassStyles
.shadowbox-shadow: 0 .125rem .25rem -.0625rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.04 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 .375rem .75rem -.125rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.05 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 .75rem 1.5rem -.25rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.06 * var(--bs-shadow-strength) * var(--bs-so, 1)));
.shadow-xsbox-shadow: 0 0.0625rem 0.125rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h/calc(0.04 * var(--bs-shadow-strength) * var(--bs-so, 1)));
.shadow-smbox-shadow: 0 .0625rem .125rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.04 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 .125rem .375rem -.0625rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.05 * var(--bs-shadow-strength) * var(--bs-so, 1)));
.shadow-lgbox-shadow: 0 .125rem .375rem -.0625rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.05 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 .375rem 1rem -.1875rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.06 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 .75rem 2rem -.375rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.07 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 1.5rem 3.5rem -.75rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.08 * var(--bs-shadow-strength) * var(--bs-so, 1)));
.shadow-xlbox-shadow: 0 .1875rem .5rem -.0625rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.05 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 .5rem 1.25rem -.1875rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.06 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 1rem 2.5rem -.375rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.07 * var(--bs-shadow-strength) * var(--bs-so, 1))), 0 2rem 5rem -.75rem oklch(from var(--bs-sc, var(--bs-shadow-color)) l c h / calc(.09 * var(--bs-shadow-strength) * var(--bs-so, 1)));
.shadow-nonebox-shadow: none;

Examples

While shadows on components are enabled by default via $enable-shadows, you can always manage shadows with our box-shadow utility classes. Includes support for .shadow-none and several sizes (which have associated variables to match).

For a more modern, smoother look, shadows are "layered" box-shadow declarations. More specifically:

  • Each shadow size token contains multiple box-shadow values that provide a more natural falloff.
  • Every layer derives its color from a global --shadow-color token by default, which .shadow-{color} utilities can override on a single element—without re-tinting any nested shadows—for quick, one-off accents.
  • Similarly, a global --shadow-strength token (1 for light mode, 2.4 for dark mode) deepens every shadow and doubles as a knob to scale all shadows at once.
No shadow
Small shadow
Regular shadow
Larger shadow
Extra large shadow
HTML
<div class="shadow-none p-3 bg-body rounded">No shadow</div>
<div class="shadow-sm p-3 bg-body rounded">Small shadow</div>
<div class="shadow p-3 bg-body rounded">Regular shadow</div>
<div class="shadow-lg p-3 bg-body rounded">Larger shadow</div>
<div class="shadow-xl p-3 bg-body rounded">Extra large shadow</div>

Shadow color

Change the color of a shadow with .shadow-{color} utilities for any theme color, plus .shadow-current (matches the element’s color), .shadow-black, and .shadow-white. Pair a color utility with a size utility. Colored shadows are intentionally subtle—use a larger size like .shadow-xl for a more visible tint.

The --bs-sc variable is registered with @property as non-inheriting (inherits: false), so shadow color utilities are scoped to the element they’re applied to and never cascade into nested elements or components. This is why --bs-sc is deliberately separate from the inheriting --bs-shadow-color design token that shadows resolve their default color from.

Primary
Success
Danger
Black
HTML
<div class="shadow-xl shadow-primary p-3 bg-body rounded">Primary</div>
<div class="shadow-xl shadow-success p-3 bg-body rounded">Success</div>
<div class="shadow-xl shadow-danger p-3 bg-body rounded">Danger</div>
<div class="shadow-xl shadow-black p-3 bg-body rounded">Black</div>

Nested elements

Because shadow color and opacity utilities set the non-inheriting --bs-sc and --bs-so variables, a parent’s .shadow-{color} or .shadow-opacity-* doesn’t affect the shadows of nested elements. Below, the parent uses .shadow-primary while the nested .shadow-xl keeps the default shadow color.

Parent with .shadow-primary
Nested .shadow-xl keeps the default color.
HTML
<div class="shadow-xl shadow-primary p-4 bg-body rounded-7">
  Parent with .shadow-primary
  <div class="shadow-xl p-3 mt-3 bg-body rounded-3">
    Nested .shadow-xl keeps the default color.
  </div>
</div>

Shadow opacity

Scale a shadow’s strength with .shadow-opacity-{10-100} utilities. Opacity is treated as a midpoint, not a ceiling: the default shadow matches .shadow-opacity-50, so lower values lighten it while higher values—up to .shadow-opacity-100—deepen it. This works with any size or color utility. Like --bs-sc, --bs-so is scoped to the element, so pair it with a size or color utility on the same element rather than expecting it to inherit.

20%
50% (default)
100%
HTML
<div class="shadow-xl shadow-opacity-20 p-3 bg-1 rounded">20%</div>
<div class="shadow-xl shadow-opacity-50 p-3 bg-body rounded">50% (default)</div>
<div class="shadow-xl shadow-opacity-100 p-3 bg-body rounded">100%</div>

Even works with custom shadow colors:

20%
50% (default)
100%
HTML
<div class="shadow-xl shadow-opacity-20 shadow-primary p-3 bg-body rounded">20%</div>
<div class="shadow-xl shadow-opacity-50 shadow-primary p-3 bg-body rounded">50% (default)</div>
<div class="shadow-xl shadow-opacity-100 shadow-primary p-3 bg-body rounded">100%</div>

CSS

Sass variables

// --box-shadow* tokens are generated below (see root-box-shadow-loop) from
// the shared $shadows map in scss/_config.scss, which reads these two.
--shadow-color: #000,
--shadow-strength: 1,
$shadows: (
  null: #{(
    "0 .125rem .25rem -.0625rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.04 * var(--shadow-strength) * var(--so, 1)))",
    "0 .375rem .75rem -.125rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.05 * var(--shadow-strength) * var(--so, 1)))",
    "0 .75rem 1.5rem -.25rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.06 * var(--shadow-strength) * var(--so, 1)))"
  )},
  xs: 0 .0625rem .125rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.04 * var(--shadow-strength) * var(--so, 1))),
  sm: #{(
    "0 .0625rem .125rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.04 * var(--shadow-strength) * var(--so, 1)))",
    "0 .125rem .375rem -.0625rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.05 * var(--shadow-strength) * var(--so, 1)))"
  )},
  lg: #{(
    "0 .125rem .375rem -.0625rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.05 * var(--shadow-strength) * var(--so, 1)))",
    "0 .375rem 1rem -.1875rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.06 * var(--shadow-strength) * var(--so, 1)))",
    "0 .75rem 2rem -.375rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.07 * var(--shadow-strength) * var(--so, 1)))",
    "0 1.5rem 3.5rem -.75rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.08 * var(--shadow-strength) * var(--so, 1)))"
  )},
  xl: #{(
    "0 .1875rem .5rem -.0625rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.05 * var(--shadow-strength) * var(--so, 1)))",
    "0 .5rem 1.25rem -.1875rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.06 * var(--shadow-strength) * var(--so, 1)))",
    "0 1rem 2.5rem -.375rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.07 * var(--shadow-strength) * var(--so, 1)))",
    "0 2rem 5rem -.75rem oklch(from var(--sc, var(--shadow-color)) l c h / calc(.09 * var(--shadow-strength) * var(--so, 1)))"
  )},
  inset: inset 0 1px 2px light-dark(oklch(from var(--sc, var(--shadow-color)) l c h / calc(8% * var(--so, 1))), oklch(from var(--sc, var(--shadow-color)) l c h / calc(26% * var(--so, 1)))),
);

Sass utilities API

Shadow utilities are declared in our utilities API in scss/_utilities.scss. Learn how to use the utilities API.

"shadow": (
  property: box-shadow,
  class: shadow,
  // Pull the literal layered expressions straight from the shared $shadows
  // map (single source of truth in scss/_config.scss, also consumed by
  // scss/_root.scss). Emitting the literal—rather than var(--box-shadow-*)—
  // keeps the nested var(--sc, var(--shadow-color)) / var(--so, 1)
  // unresolved so they resolve on the element, letting .shadow-{color} and
  // .shadow-opacity-* take effect. `inset` isn't a utility, so it's excluded.
  values: map.merge(map.remove($shadows, inset), (none: none))
),
// scss-docs-end utils-shadow
// scss-docs-start utils-shadow-color
"shadow-color": (
  // --sc is a local override composed into the $shadows expressions
  // (scss/_config.scss) as var(--sc, var(--shadow-color)); like --bc for
  // border-color, it's non-inheriting so .shadow-primary doesn't tint
  // nested .shadow-* descendants, which instead fall back to the
  // cascading global --shadow-color token (scss/_root.scss).
  property: --sc,
  class: shadow,
  values: map-merge-multiple(
    theme-color-refs("base"),
    (
      "current": currentcolor,
      "black": var(--black),
      "white": var(--white),
    )
  )
),
// scss-docs-end utils-shadow-color
// scss-docs-start utils-shadow-opacity
"shadow-opacity": (
  // --so is a local override composed into the $shadows expressions
  // (scss/_config.scss) as var(--so, 1); same rationale as --sc above,
  // it's non-inheriting so it doesn't leak to nested .shadow-* descendants.
  property: --so,
  class: shadow-opacity,
  values: $shadow-opacities
),
"shadow-color": (
  // --sc is a local override composed into the $shadows expressions
  // (scss/_config.scss) as var(--sc, var(--shadow-color)); like --bc for
  // border-color, it's non-inheriting so .shadow-primary doesn't tint
  // nested .shadow-* descendants, which instead fall back to the
  // cascading global --shadow-color token (scss/_root.scss).
  property: --sc,
  class: shadow,
  values: map-merge-multiple(
    theme-color-refs("base"),
    (
      "current": currentcolor,
      "black": var(--black),
      "white": var(--white),
    )
  )
),
"shadow-opacity": (
  // --so is a local override composed into the $shadows expressions
  // (scss/_config.scss) as var(--so, 1); same rationale as --sc above,
  // it's non-inheriting so it doesn't leak to nested .shadow-* descendants.
  property: --so,
  class: shadow-opacity,
  values: $shadow-opacities
),