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-columnCommon 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
| Variant | Description |
|---|---|
| Left-aligned with connector line | A 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 timeline | Alternating 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 timeline | Replaces 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 timeline | Each 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.
Collapsible release notes timeline
Each version entry uses Bootstrap's collapse plugin so long changelogs remain hidden until expanded, keeping the initial view scannable.
Centred split timeline
Alternating left-right layout for a company history page, using Bootstrap's grid columns and a central spine positioned with CSS.
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.