✦ A decade of Canvas craft, now driven by AI — describe it, watch it build live.Start building
Bootstrap 5Content

Bootstrap 5 Vertical Timeline

A vertical timeline is a custom UI pattern that renders a chronological list of events along a central or left-aligned vertical axis, with each entry containing a date, marker, and content block. It is composed from Bootstrap 5 utilities including flex, border, spacing, badge, and card primitives — Bootstrap ships no official timeline component. Use it to display project milestones, work history, order tracking, or any sequenced set of events.

Primary Class

d-flex flex-column

Common Use Cases

  • Displaying a company's founding history on an About page, with each decade shown as a distinct timeline entry.
  • Showing the stages of an order fulfilment process — placed, packed, dispatched, delivered — on an e-commerce order detail page.
  • Presenting a candidate's work experience and education in chronological order on a CV or portfolio site.
  • Listing software release notes and version history so users can scan what changed and when at a glance.

Variants & Classes

VariantDescription
Left-aligned with connector lineA single vertical border drawn on the left using Bootstrap's border utilities acts as the spine; each event is offset to the right with a circular marker using rounded-circle and a background colour utility.
Centred split timelineAlternating entries sit left and right of a central axis. Uses Bootstrap's grid (col-5 offset-1 col-5) plus d-flex justify-content-end on even items to push content to the correct side.
Icon marker timelineReplaces the plain circular dot with a Bootstrap badge or a small div containing a Bootstrap Icon, giving each step a semantic visual cue such as a tick, clock, or flag.
Collapsible timelineEach timeline entry includes a Bootstrap collapse toggle so long descriptions are hidden by default. Uses the collapse JavaScript plugin with a small chevron button, keeping the spine unbroken.

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Vertical Timeline</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
  <style>
    .timeline {
      position: relative;
      padding-left: 2.5rem;
    }
    .timeline::before {
      content: '';
      position: absolute;
      left: 0.6875rem;
      top: 0;
      bottom: 0;
      width: 2px;
      background-color: #dee2e6;
    }
    .timeline-item {
      position: relative;
      margin-bottom: 2rem;
    }
    .timeline-marker {
      position: absolute;
      left: -2.5rem;
      top: 0.25rem;
      width: 1.125rem;
      height: 1.125rem;
      border-radius: 50%;
      border: 2px solid #fff;
      box-shadow: 0 0 0 2px #0d6efd;
    }
  </style>
</head>
<body class="p-4">
  <h2 class="mb-4">Project History</h2>
  <div class="timeline">

    <!-- Entry 1 -->
    <div class="timeline-item">
      <div class="timeline-marker bg-primary"></div>
      <div class="card shadow-sm">
        <div class="card-body">
          <span class="badge bg-primary mb-2">January 2024</span>
          <h5 class="card-title mb-1">Project Kickoff</h5>
          <p class="card-text text-muted mb-0">Initial requirements gathered, stakeholders aligned, and the development roadmap confirmed with the client.</p>
        </div>
      </div>
    </div>

    <!-- Entry 2 -->
    <div class="timeline-item">
      <div class="timeline-marker bg-success"></div>
      <div class="card shadow-sm">
        <div class="card-body">
          <span class="badge bg-success mb-2">March 2024</span>
          <h5 class="card-title mb-1">Alpha Release</h5>
          <p class="card-text text-muted mb-0">Core features shipped to internal testers. Forty-two bugs logged, triaged, and assigned to sprint backlog.</p>
        </div>
      </div>
    </div>

    <!-- Entry 3 -->
    <div class="timeline-item">
      <div class="timeline-marker bg-warning"></div>
      <div class="card shadow-sm">
        <div class="card-body">
          <span class="badge bg-warning text-dark mb-2">June 2024</span>
          <h5 class="card-title mb-1">Beta Launch</h5>
          <p class="card-text text-muted mb-0">Public beta opened to 500 invited users. Performance metrics collected and used to optimise database queries.</p>
        </div>
      </div>
    </div>

    <!-- Entry 4 -->
    <div class="timeline-item mb-0">
      <div class="timeline-marker bg-danger"></div>
      <div class="card shadow-sm">
        <div class="card-body">
          <span class="badge bg-danger mb-2">September 2024</span>
          <h5 class="card-title mb-1">General Availability</h5>
          <p class="card-text text-muted mb-0">Version 1.0 released publicly. SLA support contracts activated and on-call rota established for production incidents.</p>
        </div>
      </div>
    </div>

  </div>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Live Examples

Order tracking timeline

A compact left-aligned timeline showing e-commerce order stages, using text utilities instead of cards to keep the layout tight on mobile.

Example 1

Collapsible release notes timeline

Each version entry uses Bootstrap's collapse plugin so long changelogs remain hidden until expanded, keeping the initial view scannable.

Example 2

Centred split timeline

Alternating left-right layout for a company history page, using Bootstrap's grid columns and a central spine positioned with CSS.

Example 3

Canvas Framework Variants

The Canvas template extends Bootstrap 5 with 1,658+ component variants. Generate any of these using Canvas Builder:

  • Left-aligned card timeline with coloured badge dates
  • Centred split timeline alternating left and right entries
  • Compact dot-and-text order tracking timeline
  • Collapsible release notes timeline with expand toggles
  • Canvas Builder generates all vertical timeline variants automatically from a text prompt describing your events

Best Practices

Use position-relative on the wrapper and position-absolute on the spine

Bootstrap's position utilities (position-relative, position-absolute) let you draw the connecting line as a pseudo-element or an empty div without adding a separate DOM element per row. Set the spine's left value to align with the centre of your marker dots to keep everything visually consistent at all viewport widths.

Collapse long entries with Bootstrap's native collapse plugin

For timelines with verbose descriptions — such as detailed release notes or case study summaries — wrap the body in a div with the collapse class and a data-bs-toggle button on the heading. This requires no custom JavaScript and keeps the visible spine intact because the collapsing element is inside the card, not the marker row itself.

Ensure the spine terminates cleanly on the last item

The spine pseudo-element spans the full height of its container. If the last timeline item has a short card, the line extends past the final dot. Fix this by setting bottom to 50% on the last .timeline-item, or by ending the spine at the last marker's vertical midpoint using a bottom value equal to half the remaining item height.

Test the layout at narrow viewports before publishing

Centred split timelines break badly on small screens because two col-5 columns leave only 2 columns of gutter for the spine. Add a media query (or Bootstrap's d-none d-sm-block on the right column) to switch to a single-column left-aligned layout below the sm breakpoint, reusing the same marker and spine CSS.

FAQ

Does Bootstrap 5 include a built-in vertical timeline component?
No. Bootstrap 5 does not ship a timeline component. The pattern shown here is built entirely from Bootstrap 5.3 utilities — flex, border, spacing, badge, card, and collapse — combined with a small amount of custom CSS for the spine line and circular markers.
How do I make the connector line stop at the last entry instead of running to the bottom of the container?
Apply position-relative to the timeline wrapper and draw the spine as a ::before pseudo-element with a top of 0. Set the bottom of the pseudo-element to 50% rather than 0, or calculate the exact pixel offset. Alternatively, give the last .timeline-item a class such as .timeline-item--last and override the ::before height using a targeted CSS rule on the parent.
Can I animate the timeline entries as the user scrolls?
Yes. Add Bootstrap's d-none class to each entry and use the Intersection Observer API in a small vanilla JS snippet to toggle d-none off and add an animation class when the element enters the viewport. Alternatively, apply a CSS animation with animation-play-state: paused and switch it to running via JavaScript on scroll. Avoid heavy animation libraries for a pattern this simple.
How do I make the timeline accessible for screen reader users?
Wrap the timeline in a <ol> or <ul> element with role='list' if the events are genuinely sequential, so assistive technologies announce the list count. Place each date inside a <time> element with a machine-readable datetime attribute, for example <time datetime='2024-01'>January 2024</time>. Ensure colour is not the only way to convey status — add a visually-hidden text label alongside each coloured marker.