Stepper

@use 'sprucecss/scss/spruce' as *;

.stepper {
  &__list {
    @include clear-list;
    counter-reset: step;
    display: grid;
    gap: spacer('s');

    @include breakpoint('md') {
      grid-auto-columns: 1fr;
      grid-auto-flow: column;
    }

    // The items sit side by side: clear the stack margins of the base list style.
    > li {
      margin-block: 0;
      padding-block: 0;
    }
  }

  &__step {
    --step-color: #{color('border-strong')};
    display: grid;
    gap: 0 spacer('s');
    grid-template-columns: auto 1fr;
    position: relative;

    @include breakpoint('md') {
      grid-template-columns: 1fr;
      text-align: center;

      &:not(:last-child)::after {
        background-color: var(--step-color);
        block-size: 2px;
        content: '';
        inline-size: calc(100% - 2.5rem - #{spacer('xs')} * 2);
        inset-block-start: 1.25rem;
        inset-inline-start: calc(50% + 1.25rem + #{spacer('xs')});
        position: absolute;
      }
    }

    &--complete {
      --step-color: #{color('primary')};
    }

    &--current {
      --step-color: #{color('primary')};
    }
  }

  &__marker {
    align-items: center;
    block-size: 2.5rem;
    border: 2px solid var(--step-color);
    border-radius: 50%;
    color: color('heading');
    display: flex;
    font-weight: 700;
    grid-row: span 2;
    inline-size: 2.5rem;
    justify-content: center;

    @include breakpoint('md') {
      grid-row: auto;
      margin-inline: auto;
    }
  }

  &__step--complete &__marker {
    background-color: var(--step-color);
    color: color('primary-foreground', 'btn');
  }

  &__step--current &__marker {
    box-shadow: 0 0 0 4px color-alpha('primary', 0.2);
  }

  &__label {
    align-self: end;
    color: color('heading');
    font-weight: 700;

    @include breakpoint('md') {
      margin-block-start: spacer('xs');
    }
  }

  &__description {
    color: color('muted');
    font-size: config('font-size-sm', $typography);
  }
}
<nav class="stepper" aria-label="Sign-up progress">
    <ol class="stepper__list" role="list">
        <li class="stepper__step stepper__step--complete">
            <span class="stepper__marker" aria-hidden="true">1</span>
            <span class="stepper__label"><span class="sr-only">Completed: </span>Account</span>
            <span class="stepper__description">Your details</span>
        </li>
        <li class="stepper__step stepper__step--current" aria-current="step">
            <span class="stepper__marker" aria-hidden="true">2</span>
            <span class="stepper__label"><span class="sr-only">Current: </span>Workspace</span>
            <span class="stepper__description">Name and style</span>
        </li>
        <li class="stepper__step">
            <span class="stepper__marker" aria-hidden="true">3</span>
            <span class="stepper__label">Team</span>
            <span class="stepper__description">Invite people</span>
        </li>
        <li class="stepper__step">
            <span class="stepper__marker" aria-hidden="true">4</span>
            <span class="stepper__label">Done</span>
            <span class="stepper__description">Start building</span>
        </li>
    </ol>
</nav>

Stepper

On this page

A progress indicator for multi-step flows like sign-up or checkout.

Technical Details

  • It is a nav with an ordered list; the current step has aria-current="step", and completed/current steps have hidden "Completed:"/"Current:" prefixes, because color and numbers alone don't convey the state.
  • Vertical on small screens, horizontal from the md breakpoint, with connector lines drawn by ::after using logical properties (RTL ready).
  • Make completed steps links if users can go back to them.

Documentation

Learn about Spruce CSS through our extensive documentation.

Components

Explore our UI library of accessible components built with Spruce CSS.

Blocks and Pages

Full-width page blocks and complete page templates, ready to copy.

Find us on GitHub

Did you find a bug? Have an idea or a question? Please open an issue to help us develop the project.