Open demo

CSS code

HTML
<ol class="rtl">
  <li class="done"><span class="mark" aria-hidden="true">✓</span><div class="head"><h2>Workspace permissions</h2><span class="tag">Shipped</span></div><p>Granular roles at project and folder level, with audit trail.</p></li>
  <li class="done"><span class="mark" aria-hidden="true">✓</span><div class="head"><h2>API v2</h2><span class="tag">Shipped</span></div><p>Cursor pagination, webhooks, and 5× higher rate limits.</p></li>
  <li class="cur" aria-current="step"><span class="mark" aria-hidden="true">▶</span><div class="head"><h2>Realtime collaboration</h2><span class="tag">In progress</span></div><p>Live cursors and presence, rolling out to beta workspaces now.</p></li>
  <li class="todo"><span class="mark" aria-hidden="true">3</span><div class="head"><h2>Mobile apps</h2><span class="tag">Q4 2026</span></div><p>Native iOS and Android with full offline parity.</p></li>
  <li class="todo"><span class="mark" aria-hidden="true">4</span><div class="head"><h2>Plugin marketplace</h2><span class="tag">Planned</span></div><p>Third-party extensions with revenue share for builders.</p></li>
</ol>
CSS
/* Status roadmap: done, current and planned items on one line that is green up to the current item.
   The status is in the visible tag text; the marks are decoration. */
.rtl{--rtl-go:#22c55e;--rtl-line:#2b3648;--rtl-muted:#7f8ba0;
  position:relative;margin:0;padding:0 0 0 34px;list-style:none}
.rtl::before{content:"";position:absolute;left:10px;top:6px;bottom:6px;width:2px;
  background:linear-gradient(180deg,var(--rtl-go) 0%,var(--rtl-go) 38%,var(--rtl-line) 38%)}
.rtl>li{position:relative;padding-bottom:30px}
.rtl>li:last-child{padding-bottom:0}
.rtl .mark{position:absolute;left:-34px;top:2px;box-sizing:border-box;width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:.65rem;font-weight:900}
.rtl .done .mark{background:#123822;color:#4ade80;border:2px solid var(--rtl-go)}
.rtl .cur .mark{background:var(--rtl-go);color:#08130c;border:2px solid var(--rtl-go);box-shadow:0 0 14px rgba(34,197,94,.5)}
.rtl .todo .mark{background:#141b26;color:var(--rtl-muted);border:2px solid var(--rtl-line)}
.rtl .head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.rtl h2{margin:0;font-size:.98rem}
.rtl .tag{font-size:.68rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:3px 9px;border-radius:999px}
.rtl .done .tag{background:#123822;color:#4ade80}
.rtl .cur .tag{background:#1c2a17;color:#a3e635}
.rtl .todo .tag{background:#1a2230;color:var(--rtl-muted)}
.rtl p{margin:6px 0 0;font-size:.85rem;line-height:1.6;color:#96a1b5;max-width:46ch}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<ol class="rtl list-unstyled mb-0">
  <li class="done"><span class="mark rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">✓</span><div class="head d-flex align-items-center flex-wrap"><h2 class="fw-bold mb-0">Workspace permissions</h2><span class="badge rounded-pill text-uppercase">Shipped</span></div><p class="mb-0">Granular roles at project and folder level, with audit trail.</p></li>
  <li class="done"><span class="mark rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">✓</span><div class="head d-flex align-items-center flex-wrap"><h2 class="fw-bold mb-0">API v2</h2><span class="badge rounded-pill text-uppercase">Shipped</span></div><p class="mb-0">Cursor pagination, webhooks, and 5× higher rate limits.</p></li>
  <li class="cur" aria-current="step"><span class="mark rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">▶</span><div class="head d-flex align-items-center flex-wrap"><h2 class="fw-bold mb-0">Realtime collaboration</h2><span class="badge rounded-pill text-uppercase">In progress</span></div><p class="mb-0">Live cursors and presence, rolling out to beta workspaces now.</p></li>
  <li class="todo"><span class="mark rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">3</span><div class="head d-flex align-items-center flex-wrap"><h2 class="fw-bold mb-0">Mobile apps</h2><span class="badge rounded-pill text-uppercase">Q4 2026</span></div><p class="mb-0">Native iOS and Android with full offline parity.</p></li>
  <li class="todo"><span class="mark rounded-circle d-flex align-items-center justify-content-center" aria-hidden="true">4</span><div class="head d-flex align-items-center flex-wrap"><h2 class="fw-bold mb-0">Plugin marketplace</h2><span class="badge rounded-pill text-uppercase">Planned</span></div><p class="mb-0">Third-party extensions with revenue share for builders.</p></li>
</ol>
CSS
/* Status roadmap on a .list-unstyled list; the status tags are Bootstrap .badge.rounded-pill
   restyled through --bs-badge-*. The line is green up to the current item; marks are decoration. */
.rtl{--rtl-go:#22c55e;--rtl-line:#2b3648;--rtl-muted:#7f8ba0;position:relative;padding-left:34px}
.rtl::before{content:"";position:absolute;left:10px;top:6px;bottom:6px;width:2px;
  background:linear-gradient(180deg,var(--rtl-go) 0%,var(--rtl-go) 38%,var(--rtl-line) 38%)}
.rtl>li{position:relative;padding-bottom:30px}
.rtl>li:last-child{padding-bottom:0}
.rtl .mark{position:absolute;left:-34px;top:2px;width:22px;height:22px;font-size:.65rem;font-weight:900}
.rtl .done .mark{background:#123822;color:#4ade80;border:2px solid var(--rtl-go)}
.rtl .cur .mark{background:var(--rtl-go);color:#08130c;border:2px solid var(--rtl-go);box-shadow:0 0 14px rgba(34,197,94,.5)}
.rtl .todo .mark{background:#141b26;color:var(--rtl-muted);border:2px solid var(--rtl-line)}
.rtl .head{column-gap:10px}
.rtl h2{font-size:.98rem;line-height:normal}
.rtl .badge{--bs-badge-padding-x:9px;--bs-badge-padding-y:3px;--bs-badge-font-size:.68rem;--bs-badge-font-weight:800;line-height:normal;letter-spacing:.06em}
.rtl .done .badge{--bs-badge-color:#4ade80;background:#123822}
.rtl .cur .badge{--bs-badge-color:#a3e635;background:#1c2a17}
.rtl .todo .badge{--bs-badge-color:var(--rtl-muted);background:#1a2230}
.rtl p{margin-top:6px;font-size:.85rem;line-height:1.6;color:#96a1b5;max-width:46ch}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<ol class="relative pl-[34px] before:absolute before:top-1.5 before:bottom-1.5 before:left-2.5 before:w-0.5 before:bg-[linear-gradient(180deg,#22c55e_0%,#22c55e_38%,#2b3648_38%)]">
  <li class="relative pb-[30px]"><span aria-hidden="true" class="absolute top-0.5 -left-[34px] flex size-[22px] items-center justify-center rounded-full border-2 border-[#22c55e] bg-[#123822] text-[.65rem] font-black text-[#4ade80]">✓</span><div class="flex flex-wrap items-center gap-2.5"><h2 class="text-[.98rem] font-bold">Workspace permissions</h2><span class="rounded-full bg-[#123822] px-[9px] py-[3px] text-[.68rem] font-extrabold tracking-[.06em] text-[#4ade80] uppercase">Shipped</span></div><p class="mt-1.5 max-w-[46ch] text-[.85rem] leading-[1.6] text-[#96a1b5]">Granular roles at project and folder level, with audit trail.</p></li>
  <li class="relative pb-[30px]"><span aria-hidden="true" class="absolute top-0.5 -left-[34px] flex size-[22px] items-center justify-center rounded-full border-2 border-[#22c55e] bg-[#123822] text-[.65rem] font-black text-[#4ade80]">✓</span><div class="flex flex-wrap items-center gap-2.5"><h2 class="text-[.98rem] font-bold">API v2</h2><span class="rounded-full bg-[#123822] px-[9px] py-[3px] text-[.68rem] font-extrabold tracking-[.06em] text-[#4ade80] uppercase">Shipped</span></div><p class="mt-1.5 max-w-[46ch] text-[.85rem] leading-[1.6] text-[#96a1b5]">Cursor pagination, webhooks, and 5× higher rate limits.</p></li>
  <li class="relative pb-[30px]" aria-current="step"><span aria-hidden="true" class="absolute top-0.5 -left-[34px] flex size-[22px] items-center justify-center rounded-full border-2 border-[#22c55e] bg-[#22c55e] text-[.65rem] font-black text-[#08130c] shadow-[0_0_14px_rgba(34,197,94,.5)]">▶</span><div class="flex flex-wrap items-center gap-2.5"><h2 class="text-[.98rem] font-bold">Realtime collaboration</h2><span class="rounded-full bg-[#1c2a17] px-[9px] py-[3px] text-[.68rem] font-extrabold tracking-[.06em] text-[#a3e635] uppercase">In progress</span></div><p class="mt-1.5 max-w-[46ch] text-[.85rem] leading-[1.6] text-[#96a1b5]">Live cursors and presence, rolling out to beta workspaces now.</p></li>
  <li class="relative pb-[30px]"><span aria-hidden="true" class="absolute top-0.5 -left-[34px] flex size-[22px] items-center justify-center rounded-full border-2 border-[#2b3648] bg-[#141b26] text-[.65rem] font-black text-[#7f8ba0]">3</span><div class="flex flex-wrap items-center gap-2.5"><h2 class="text-[.98rem] font-bold">Mobile apps</h2><span class="rounded-full bg-[#1a2230] px-[9px] py-[3px] text-[.68rem] font-extrabold tracking-[.06em] text-[#7f8ba0] uppercase">Q4 2026</span></div><p class="mt-1.5 max-w-[46ch] text-[.85rem] leading-[1.6] text-[#96a1b5]">Native iOS and Android with full offline parity.</p></li>
  <li class="relative"><span aria-hidden="true" class="absolute top-0.5 -left-[34px] flex size-[22px] items-center justify-center rounded-full border-2 border-[#2b3648] bg-[#141b26] text-[.65rem] font-black text-[#7f8ba0]">4</span><div class="flex flex-wrap items-center gap-2.5"><h2 class="text-[.98rem] font-bold">Plugin marketplace</h2><span class="rounded-full bg-[#1a2230] px-[9px] py-[3px] text-[.68rem] font-extrabold tracking-[.06em] text-[#7f8ba0] uppercase">Planned</span></div><p class="mt-1.5 max-w-[46ch] text-[.85rem] leading-[1.6] text-[#96a1b5]">Third-party extensions with revenue share for builders.</p></li>
</ol>

About this set

A dark product roadmap that shows status as well as order. Five items run down a thin line: two are Shipped with a green tick, one is In progress with a glowing green play mark, and two are planned, one tagged Q4 2026 and one Planned, with a numbered grey mark. The line itself is green up to the current work and slate after it, so progress reads at a glance. Each item has a heading, a pill-shaped status tag beside it and a short description. Use it on a public roadmap, a changelog that looks ahead, or a project status page on a dark theme. The status lives in the visible tag text, not in the colour, so it survives greyscale and screen readers. The marks are decorative and aria-hidden, the current item carries aria-current, and the whole thing is an ordered list. Status styles come from three classes on the list item: done, cur and todo. The Bootstrap version renders the tags as .badge.rounded-pill restyled through –bs-badge-* variables, and the Tailwind version writes the same colours as arbitrary values.

What’s included

  • Done, current and planned states from one class per item
  • Status written in a visible tag, not only in colour
  • Line coloured green up to the current item
  • Current item marked with aria-current
  • Bootstrap tags use .badge with --bs-badge-* variables

Accessibility

The roadmap is an ordered list with a heading per item. The tick, play and number marks are aria-hidden because the tag text already states the status, and the in-progress item has aria-current. Every tag and description passes 4.5:1 on the dark background. Nothing animates.

Customise it

Change --rtl-go (green), --rtl-line and --rtl-muted on .rtl, and the 38% stop in the ::before gradient to move where the green line ends. In Bootstrap the tag colours are --bs-badge-color plus a background per state; in Tailwind edit the #22c55e and #2b3648 values.