Open demo

CSS code

HTML
<ol class="mst">
  <li><div class="num" aria-hidden="true">1</div><div class="card"><h2><span class="sr-only">Step 1: </span>Connect your data</h2><p>Point us at your database or upload a CSV — either takes about two minutes.</p></div></li>
  <li><div class="num" aria-hidden="true">2</div><div class="card"><h2><span class="sr-only">Step 2: </span>Pick a template</h2><p>Start from a dashboard that already fits your industry, then bend it to taste.</p></div></li>
  <li><div class="num" aria-hidden="true">3</div><div class="card"><h2><span class="sr-only">Step 3: </span>Invite the team</h2><p>Everyone gets the same live view, with roles deciding who can edit what.</p></div></li>
  <li><div class="num" aria-hidden="true">4</div><div class="card"><h2><span class="sr-only">Step 4: </span>Automate reports</h2><p>Schedule a Monday-morning digest and stop building slide decks by hand.</p></div></li>
</ol>
CSS
/* Milestone cards: numbered circles joined by a line, equal-height cards below. Stacks under 720px. */
.mst{--mst-accent:#2563eb;--mst-line:#c9d8f2;--mst-muted:#5d6b88;
  display:flex;width:100%;max-width:960px;align-items:stretch;margin:0;padding:0;list-style:none}
.mst>li{flex:1;position:relative;padding:0 14px}
.mst>li::before{content:"";position:absolute;top:26px;left:0;right:0;height:3px;background:var(--mst-line)}
.mst>li:first-child::before{left:50%}
.mst>li:last-child::before{right:50%}
.mst .num{position:relative;box-sizing:border-box;width:52px;height:52px;margin:0 auto 18px;border-radius:50%;background:#fff;border:3px solid var(--mst-accent);
  color:var(--mst-accent);font-weight:900;font-size:1.05rem;display:flex;align-items:center;justify-content:center;z-index:1;
  box-shadow:0 8px 20px -8px rgba(37,99,235,.4)}
.mst .card{box-sizing:border-box;background:#fff;border:1px solid #dfe8f7;border-radius:14px;padding:18px;height:calc(100% - 70px);
  box-shadow:0 14px 30px -20px rgba(20,40,90,.25);transition:transform .15s}
.mst .card:hover{transform:translateY(-4px)}
.mst h2{margin:0 0 6px;font-size:.92rem;text-align:center}
.mst .card p{margin:0;font-size:.8rem;line-height:1.6;color:var(--mst-muted);text-align:center}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media (max-width:720px){.mst{flex-direction:column;gap:20px;max-width:340px}.mst>li::before{display:none}.mst .card{height:auto}}
@media (prefers-reduced-motion:reduce){.mst .card{transition:none}.mst .card:hover{transform:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<ol class="mst d-flex align-items-stretch list-unstyled mb-0">
  <li><div class="num rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">1</div><div class="card text-center"><div class="card-body"><h2 class="card-title fw-bold"><span class="visually-hidden">Step 1: </span>Connect your data</h2><p class="card-text">Point us at your database or upload a CSV — either takes about two minutes.</p></div></div></li>
  <li><div class="num rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">2</div><div class="card text-center"><div class="card-body"><h2 class="card-title fw-bold"><span class="visually-hidden">Step 2: </span>Pick a template</h2><p class="card-text">Start from a dashboard that already fits your industry, then bend it to taste.</p></div></div></li>
  <li><div class="num rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">3</div><div class="card text-center"><div class="card-body"><h2 class="card-title fw-bold"><span class="visually-hidden">Step 3: </span>Invite the team</h2><p class="card-text">Everyone gets the same live view, with roles deciding who can edit what.</p></div></div></li>
  <li><div class="num rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">4</div><div class="card text-center"><div class="card-body"><h2 class="card-title fw-bold"><span class="visually-hidden">Step 4: </span>Automate reports</h2><p class="card-text">Schedule a Monday-morning digest and stop building slide decks by hand.</p></div></div></li>
</ol>
CSS
/* Milestone cards: .rounded-circle numbers joined by a line, equal-height Bootstrap .card items below
   (restyled through --bs-card-*). Stacks under 720px. */
.mst{--mst-accent:#2563eb;--mst-line:#c9d8f2;--mst-muted:#5d6b88;width:100%;max-width:960px}
.mst>li{flex:1;position:relative;padding:0 14px}
.mst>li::before{content:"";position:absolute;top:26px;left:0;right:0;height:3px;background:var(--mst-line)}
.mst>li:first-child::before{left:50%}
.mst>li:last-child::before{right:50%}
.mst .num{position:relative;width:52px;height:52px;margin:0 auto 18px;background:#fff;border:3px solid var(--mst-accent);color:var(--mst-accent);
  font-weight:900;font-size:1.05rem;z-index:1;box-shadow:0 8px 20px -8px rgba(37,99,235,.4)}
.mst .card{--bs-card-border-color:#dfe8f7;--bs-card-border-radius:14px;--bs-card-spacer-y:18px;--bs-card-spacer-x:18px;--bs-card-title-spacer-y:6px;
  height:calc(100% - 70px);box-shadow:0 14px 30px -20px rgba(20,40,90,.25);transition:transform .15s}
.mst .card:hover{transform:translateY(-4px)}
.mst .card-title{font-size:.92rem;line-height:normal}
.mst .card-text{font-size:.8rem;line-height:1.6;color:var(--mst-muted)}
@media (max-width:720px){.mst{flex-direction:column;gap:20px;max-width:340px}.mst>li::before{display:none}.mst .card{height:auto}}
@media (prefers-reduced-motion:reduce){.mst .card{transition:none}.mst .card:hover{transform:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<ol class="flex w-full max-w-[340px] flex-col items-stretch gap-5 min-[721px]:max-w-[960px] min-[721px]:flex-row min-[721px]:gap-0">
  <li class="relative flex-1 px-3.5 min-[721px]:before:absolute min-[721px]:before:top-[26px] min-[721px]:before:right-0 min-[721px]:before:left-0 min-[721px]:before:h-[3px] min-[721px]:before:bg-[#c9d8f2] min-[721px]:first:before:left-1/2 min-[721px]:last:before:right-1/2"><div aria-hidden="true" class="relative z-[1] mx-auto mb-[18px] flex size-[52px] items-center justify-center rounded-full border-3 border-[#2563eb] bg-white text-[1.05rem] font-black text-[#2563eb] shadow-[0_8px_20px_-8px_rgba(37,99,235,.4)]">1</div><div class="rounded-[14px] border border-[#dfe8f7] bg-white p-[18px] text-center shadow-[0_14px_30px_-20px_rgba(20,40,90,.25)] transition-transform duration-150 hover:-translate-y-1 motion-reduce:transition-none motion-reduce:hover:translate-y-0 min-[721px]:h-[calc(100%-70px)]"><h2 class="mb-1.5 text-[.92rem] font-bold"><span class="sr-only">Step 1: </span>Connect your data</h2><p class="text-[.8rem] leading-[1.6] text-[#5d6b88]">Point us at your database or upload a CSV — either takes about two minutes.</p></div></li>
  <li class="relative flex-1 px-3.5 min-[721px]:before:absolute min-[721px]:before:top-[26px] min-[721px]:before:right-0 min-[721px]:before:left-0 min-[721px]:before:h-[3px] min-[721px]:before:bg-[#c9d8f2] min-[721px]:first:before:left-1/2 min-[721px]:last:before:right-1/2"><div aria-hidden="true" class="relative z-[1] mx-auto mb-[18px] flex size-[52px] items-center justify-center rounded-full border-3 border-[#2563eb] bg-white text-[1.05rem] font-black text-[#2563eb] shadow-[0_8px_20px_-8px_rgba(37,99,235,.4)]">2</div><div class="rounded-[14px] border border-[#dfe8f7] bg-white p-[18px] text-center shadow-[0_14px_30px_-20px_rgba(20,40,90,.25)] transition-transform duration-150 hover:-translate-y-1 motion-reduce:transition-none motion-reduce:hover:translate-y-0 min-[721px]:h-[calc(100%-70px)]"><h2 class="mb-1.5 text-[.92rem] font-bold"><span class="sr-only">Step 2: </span>Pick a template</h2><p class="text-[.8rem] leading-[1.6] text-[#5d6b88]">Start from a dashboard that already fits your industry, then bend it to taste.</p></div></li>
  <li class="relative flex-1 px-3.5 min-[721px]:before:absolute min-[721px]:before:top-[26px] min-[721px]:before:right-0 min-[721px]:before:left-0 min-[721px]:before:h-[3px] min-[721px]:before:bg-[#c9d8f2] min-[721px]:first:before:left-1/2 min-[721px]:last:before:right-1/2"><div aria-hidden="true" class="relative z-[1] mx-auto mb-[18px] flex size-[52px] items-center justify-center rounded-full border-3 border-[#2563eb] bg-white text-[1.05rem] font-black text-[#2563eb] shadow-[0_8px_20px_-8px_rgba(37,99,235,.4)]">3</div><div class="rounded-[14px] border border-[#dfe8f7] bg-white p-[18px] text-center shadow-[0_14px_30px_-20px_rgba(20,40,90,.25)] transition-transform duration-150 hover:-translate-y-1 motion-reduce:transition-none motion-reduce:hover:translate-y-0 min-[721px]:h-[calc(100%-70px)]"><h2 class="mb-1.5 text-[.92rem] font-bold"><span class="sr-only">Step 3: </span>Invite the team</h2><p class="text-[.8rem] leading-[1.6] text-[#5d6b88]">Everyone gets the same live view, with roles deciding who can edit what.</p></div></li>
  <li class="relative flex-1 px-3.5 min-[721px]:before:absolute min-[721px]:before:top-[26px] min-[721px]:before:right-0 min-[721px]:before:left-0 min-[721px]:before:h-[3px] min-[721px]:before:bg-[#c9d8f2] min-[721px]:first:before:left-1/2 min-[721px]:last:before:right-1/2"><div aria-hidden="true" class="relative z-[1] mx-auto mb-[18px] flex size-[52px] items-center justify-center rounded-full border-3 border-[#2563eb] bg-white text-[1.05rem] font-black text-[#2563eb] shadow-[0_8px_20px_-8px_rgba(37,99,235,.4)]">4</div><div class="rounded-[14px] border border-[#dfe8f7] bg-white p-[18px] text-center shadow-[0_14px_30px_-20px_rgba(20,40,90,.25)] transition-transform duration-150 hover:-translate-y-1 motion-reduce:transition-none motion-reduce:hover:translate-y-0 min-[721px]:h-[calc(100%-70px)]"><h2 class="mb-1.5 text-[.92rem] font-bold"><span class="sr-only">Step 4: </span>Automate reports</h2><p class="text-[.8rem] leading-[1.6] text-[#5d6b88]">Schedule a Monday-morning digest and stop building slide decks by hand.</p></div></li>
</ol>

About this set

Four onboarding milestones in a row: Connect your data, Pick a template, Invite the team and Automate reports. Each step has a large numbered circle with a blue ring and a soft blue shadow, joined to its neighbours by a pale line, and a centred card below with a heading and two lines of text. The cards stretch to equal height, so uneven copy still lines up. Use it for how it works sections on landing pages, onboarding explainers and short processes of three to five steps where each step needs a sentence. The steps are an ordered list. The circles are aria-hidden and each heading starts with visually hidden text such as Step 1, so a screen reader hears the number once, in the heading, instead of a stray digit. Cards lift 4 pixels on hover, which stops under prefers-reduced-motion. Under 720 pixels the row becomes a single column of steps at most 340 pixels wide and the connecting line is hidden. The Bootstrap version uses .card, .rounded-circle and .visually-hidden, and the Tailwind version uses first: and last: variants to trim the line at the ends.

What’s included

  • Numbered circles joined by a connecting line
  • Equal-height cards across the row
  • Step number moved into each heading as hidden text
  • Single column under 720px
  • Hover lift switched off under reduced motion

Accessibility

The milestones are an ordered list with a heading each. The visible numbers are aria-hidden and repeated as visually hidden Step 1 to Step 4 text at the start of each heading, so headings are meaningful on their own in a headings list. Text passes 4.5:1. The hover transform is removed when reduced motion is requested.

Customise it

Change --mst-accent, --mst-line and --mst-muted on .mst; Bootstrap cards also take --bs-card-border-color and --bs-card-spacer-x. In Tailwind edit border-[#2563eb], bg-[#c9d8f2] on the line and the min-[721px]: breakpoint.