Shadows

Soft shadows made from four stacked layers. Every shadow has the same layers, so you can animate from one to another.

Scale

--ui-shadow-1 is the smallest and --ui-shadow-5 the largest. --ui-shadow-0 is no shadow.

0
1
2
3
4
5
.card {
  box-shadow: var(--ui-shadow-3);
}

Inset

--ui-shadow-inset-1 to --ui-shadow-inset-3 make a surface look pressed in, like a well. --ui-shadow-inset-0 is no inset shadow.

0
1
2
3
.well {
  box-shadow: var(--ui-shadow-inset-2);
}

Shiny

--ui-shadow-shiny-1 to --ui-shadow-shiny-3 make a surface look rounded and glossy, as if it catches the light. Each one is a lit rim and an inner glow on top of the drop shadow of the same level. --ui-shadow-shiny-0 is no shiny shadow. The light shows best on a surface that is darker than white. Hover a card to raise it one level.

0
1
2
3
.button {
  box-shadow: var(--ui-shadow-shiny-1);
  transition: box-shadow 400ms var(--ease-glide);

  &:hover {
    box-shadow: var(--ui-shadow-shiny-2);
  }
}

The light is white by default and weaker in dark mode. Change it with --ui-shadow-shine-color. It also has no value until you set one, and works the same way as --ui-shadow-color.

Classes

Every shadow also has a class with the same name, without the --ui- prefix: .shadow-0 to .shadow-5, .shadow-inset-0 to .shadow-inset-3 and .shadow-shiny-0 to .shadow-shiny-3. Use them when an element has no CSS of its own. Set --ui-shadow-color on the element, or on a parent, to color its shadow.

shadow-3
shadow-inset-2
shadow-shiny-2
Tinted
<article class="card shadow-3">...</article>
<div class="shadow-inset-2">...</div>
<button class="shadow-shiny-2">Generate</button>
<article
  class="card shadow-3"
  style="
    --ui-shadow-color: color-mix(in oklch, var(--ui-primary) 40%, transparent);
  "
>
  ...
</article>

Animate

Transition box-shadow between two tokens. To animate a shadow in from nothing, start at --ui-shadow-0, not none. Hover the card.

Hover me
.card {
  box-shadow: var(--ui-shadow-1);
  transition: box-shadow 400ms var(--ease-glide);

  &:hover {
    box-shadow: var(--ui-shadow-4);
  }
}

Stack

Add your own layers after the token, separated by a comma. To keep the animation, give both states the same number of layers. Put inset layers in the same place in both states.

Hover me
.card {
  box-shadow:
    var(--ui-shadow-1),
    0 0 0 1px var(--ui-neutral-200);
  transition: box-shadow 400ms var(--ease-glide);

  &:hover {
    box-shadow:
      var(--ui-shadow-4),
      0 0 0 4px var(--ui-primary-200);
  }
}

To animate between a raised and a pressed state, use both kinds in both states. Only the levels change, so each layer has a partner to animate to. Press the card.

Press me
.card {
  box-shadow: var(--ui-shadow-1), var(--ui-shadow-inset-0);
  transition: box-shadow 400ms var(--ease-glide);

  &:hover {
    box-shadow: var(--ui-shadow-3), var(--ui-shadow-inset-0);
  }

  &:active {
    box-shadow: var(--ui-shadow-0), var(--ui-shadow-inset-1);
  }
}

Color

All layers get their color from --ui-shadow-color. It has no value until you set one, so the default is used. Set it on :root to change every shadow on the page, also inside [data-ui-theme] elements. Set it on a [data-ui-theme] element to change the shadows of that element and everything inside it. The shadow classes also pick up a color set on the element itself.

Tinted
[data-ui-theme] {
  --ui-shadow-color: color-mix(in oklch, var(--ui-primary) 40%, transparent);
  box-shadow: var(--ui-shadow-3);
}

Search 5021 icons

Type a name to find icons from the Tabler icon set.

      Move Open Esc Close