SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/timelines

8 CSS Timelines

8 Pure CSSPublished 2026-10-04Free · no sign-up

Eight timeline layouts: a vertical company history, an alternating centre line that collapses on phones, a horizontal roadmap with scroll snapping, an order activity log, a story with image cards, a numbered process, a product changelog and a compact sidebar timeline.

01. Vertical Timeline

TimelineHistory

A company history timeline with a line down the left, a dot for each event, the year and a short description. It is an ordered list because the order matters, and years are time elements with machine-readable datetime values.

View code
<ol class="tl1">
  <li><time datetime="2019">2019</time><h3>First market stall</h3><p>Twelve mugs and a borrowed table.</p></li>
  <li><time datetime="2021">2021</time><h3>Online shop opens</h3><p>Orders from 14 countries in the first year.</p></li>
  <li><time datetime="2024">2024</time><h3>New studio</h3><p>Two kilns and a team of five.</p></li>
</ol>
.tl1 { box-sizing: border-box; max-width: 100%; width: 360px; margin: 0; padding: 0 0 0 26px; list-style: none; border-left: 2px solid #e4e7ec; font-family: Inter, system-ui, sans-serif; }
.tl1 li { position: relative; padding-bottom: 22px; }
.tl1 li::before { content: ""; position: absolute; left: -34px; top: 2px; width: 12px; height: 12px; border: 3px solid #fff; border-radius: 50%; background: #2563eb; box-shadow: 0 0 0 2px #2563eb; }
.tl1 time { color: #2563eb; font-weight: 800; font-size: 13px; }
.tl1 h3 { margin: 2px 0 4px; color: #101828; font-size: 16px; }
.tl1 p { margin: 0; color: #475467; font-size: 14px; }

02. Alternating Centre Timeline

TimelineLayout

Events alternate left and right of a central line on wide screens and collapse to a single column on narrow ones. The alternation is done with grid placement and :nth-child, so the HTML order stays chronological for assistive technology.

View code
<ol class="tl2">
  <li><time datetime="2026-01">Jan</time><p>Brand refresh launched</p></li>
  <li><time datetime="2026-04">Apr</time><p>Mobile app in beta</p></li>
  <li><time datetime="2026-07">Jul</time><p>10,000 customers</p></li>
  <li><time datetime="2026-10">Oct</time><p>Opened a second warehouse</p></li>
</ol>
.tl2 { box-sizing: border-box; max-width: 100%; width: 460px; position: relative; display: grid; grid-template-columns: 1fr 1fr; gap: 14px 40px; margin: 0; padding: 0; list-style: none; font-family: Inter, system-ui, sans-serif; }
.tl2::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; background: #2c3346; transform: translateX(-50%); }
.tl2 li { position: relative; padding: 12px 14px; border: 1px solid #2c3346; border-radius: 12px; background: #151a26; }
.tl2 li:nth-child(odd) { grid-column: 1; text-align: right; }
.tl2 li:nth-child(even) { grid-column: 2; margin-top: 40px; }
.tl2 li::after { content: ""; position: absolute; top: 16px; width: 12px; height: 12px; border-radius: 50%; background: #a78bfa; }
.tl2 li:nth-child(odd)::after { right: -27px; }
.tl2 li:nth-child(even)::after { left: -27px; }
.tl2 time { color: #c4b5fd; font-weight: 800; font-size: 13px; }
.tl2 p { margin: 2px 0 0; color: #e7ebf5; font-size: 14px; }
@media (max-width: 420px) { .tl2 { grid-template-columns: 1fr; padding-left: 20px; } .tl2::before { left: 0; } .tl2 li:nth-child(n) { grid-column: 1; text-align: left; margin-top: 0; } .tl2 li:nth-child(n)::after { left: -26px; right: auto; } }

03. Horizontal Roadmap

RoadmapScroll

A product roadmap laid out horizontally with Done, Now and Next stages. On small screens the row scrolls sideways with scroll snapping, the scroll area is focusable for keyboard users, and each stage's status is written in text.

View code
<ol class="tl3" tabindex="0" aria-label="Roadmap">
  <li class="done"><b>Q1</b><span>Done</span><p>Gift cards</p></li>
  <li class="done"><b>Q2</b><span>Done</span><p>Multi-currency</p></li>
  <li class="now"><b>Q3</b><span>In progress</span><p>Wholesale portal</p></li>
  <li><b>Q4</b><span>Planned</span><p>Subscriptions</p></li>
</ol>
.tl3 { box-sizing: border-box; max-width: 100%; width: 460px; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(130px, 1fr); gap: 10px; margin: 0; padding: 4px 2px 10px; overflow-x: auto; list-style: none; scroll-snap-type: x mandatory; font-family: Inter, system-ui, sans-serif; }
.tl3:focus-visible { outline: 2px solid #2563eb; }
.tl3 li { scroll-snap-align: start; padding: 14px; border-top: 4px solid #d0d5dd; border-radius: 10px; background: #fff; box-shadow: 0 6px 18px -12px rgba(16,24,40,.3); }
.tl3 .done { border-top-color: #16a34a; }
.tl3 .now { border-top-color: #2563eb; }
.tl3 b { color: #101828; }
.tl3 span { display: block; margin: 2px 0 6px; color: #5d6679; font-size: 12px; font-weight: 600; }
.tl3 p { margin: 0; color: #101828; font-size: 14px; font-weight: 600; }

04. Activity Log Timeline

ActivityFeed

An order activity log with icons on the line for each event type, a description and a relative time. The icons are decorative and the event text says what happened, so the log reads correctly as a plain list.

View code
<ol class="tl4">
  <li><span class="i ok" aria-hidden="true">&#10003;</span><p>Order delivered</p><time datetime="2026-10-04T10:20">Today, 10:20</time></li>
  <li><span class="i" aria-hidden="true">&#128666;</span><p>Out for delivery</p><time datetime="2026-10-04T07:05">Today, 07:05</time></li>
  <li><span class="i" aria-hidden="true">&#128230;</span><p>Packed and labelled</p><time datetime="2026-10-03T16:40">Yesterday, 16:40</time></li>
</ol>
.tl4 { box-sizing: border-box; max-width: 100%; width: 340px; margin: 0; padding: 0; list-style: none; font-family: Inter, system-ui, sans-serif; }
.tl4 li { position: relative; display: grid; grid-template-columns: 34px 1fr; gap: 0 12px; padding-bottom: 18px; }
.tl4 li:not(:last-child)::before { content: ""; position: absolute; left: 16px; top: 34px; bottom: 0; width: 2px; background: #2c3346; }
.tl4 .i { grid-row: span 2; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: #1e2433; font-size: 15px; }
.tl4 .ok { background: #34d399; color: #062b1f; font-weight: 800; }
.tl4 p { margin: 4px 0 0; color: #fff; font-size: 14.5px; font-weight: 600; }
.tl4 time { color: #9aa4b8; font-size: 13px; }

05. Timeline with Image Cards

StoryCards

A storytelling timeline where each milestone is a card with an image area, a date and text, joined by a line. The image areas are CSS placeholders here; replace them with real photos and meaningful alt text describing each moment.

View code
<ol class="tl5">
  <li><div class="im" style="--c:#fde68a"></div><div><time datetime="2022-03">March 2022</time><h3>The first collection</h3><p>Six colours, all mixed in the kitchen.</p></div></li>
  <li><div class="im" style="--c:#bfdbfe"></div><div><time datetime="2023-09">September 2023</time><h3>Our own kiln</h3><p>Firing times cut from days to hours.</p></div></li>
</ol>
.tl5 { box-sizing: border-box; max-width: 100%; width: 420px; position: relative; display: grid; gap: 16px; margin: 0; padding: 0 0 0 22px; list-style: none; font-family: Inter, system-ui, sans-serif; }
.tl5::before { content: ""; position: absolute; left: 6px; top: 8px; bottom: 8px; width: 2px; background: #d0d5dd; }
.tl5 li { position: relative; display: grid; grid-template-columns: 90px minmax(0, 1fr); gap: 14px; padding: 12px; border: 1px solid #e4e7ec; border-radius: 14px; background: #fff; }
.tl5 li::before { content: ""; position: absolute; left: -21px; top: 20px; width: 12px; height: 12px; border-radius: 50%; background: #f59e0b; }
.tl5 .im { border-radius: 10px; background: var(--c); min-height: 70px; }
.tl5 time { color: #b45309; font-weight: 700; font-size: 12.5px; }
.tl5 h3 { margin: 2px 0 4px; color: #101828; font-size: 15px; }
.tl5 p { margin: 0; color: #475467; font-size: 13.5px; }

06. Process Timeline with Numbers

ProcessSteps

A how-we-work timeline with numbered circles generated by CSS counters on an ordered list, a heading and a short description for each stage. The numbers come from the list itself, so reordering steps never breaks the numbering.

View code
<ol class="tl6">
  <li><h3>Discovery call</h3><p>We learn what you sell and who buys it.</p></li>
  <li><h3>Design</h3><p>Two layout options, one round of changes.</p></li>
  <li><h3>Build and launch</h3><p>Your shop goes live within three weeks.</p></li>
</ol>
.tl6 { box-sizing: border-box; max-width: 100%; width: 360px; margin: 0; padding: 0; list-style: none; counter-reset: st; font-family: Inter, system-ui, sans-serif; }
.tl6 li { position: relative; padding: 0 0 22px 52px; counter-increment: st; }
.tl6 li::before { content: counter(st); position: absolute; left: 0; top: 0; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, #22d3ee, #6366f1); color: #fff; font-weight: 800; }
.tl6 li:not(:last-child)::after { content: ""; position: absolute; left: 17px; top: 40px; bottom: 4px; width: 2px; background: #2c3346; }
.tl6 h3 { margin: 6px 0 4px; color: #fff; font-size: 16px; }
.tl6 p { margin: 0; color: #aab3c7; font-size: 14px; }

07. Changelog Timeline

ChangelogDocs

A product changelog with version numbers, dates and typed entries like New, Improved and Fixed. Each release is an article with a heading, the type labels are text badges, and dates use time elements for machines and people.

View code
<div class="tl7">
  <article><header><h3>v2.4</h3><time datetime="2026-09-30">30 Sep 2026</time></header><ul><li><span class="n">New</span>Bulk edit for prices</li><li><span class="f">Fixed</span>Currency rounding on invoices</li></ul></article>
  <article><header><h3>v2.3</h3><time datetime="2026-09-12">12 Sep 2026</time></header><ul><li><span class="i">Improved</span>Faster image uploads</li></ul></article>
</div>
.tl7 { box-sizing: border-box; max-width: 100%; width: 400px; display: grid; gap: 14px; font-family: Inter, system-ui, sans-serif; }
.tl7 article { padding: 0 0 14px 18px; border-left: 2px solid #e4e7ec; }
.tl7 header { display: flex; align-items: baseline; gap: 10px; }
.tl7 h3 { margin: 0; color: #101828; font-size: 17px; }
.tl7 time { color: #5d6679; font-size: 13px; }
.tl7 ul { display: grid; gap: 6px; margin: 8px 0 0; padding: 0; list-style: none; color: #344054; font-size: 14px; }
.tl7 li span { display: inline-block; min-width: 64px; margin-right: 8px; padding: 1px 7px; border-radius: 6px; font-size: 11.5px; font-weight: 700; text-align: center; }
.n { background: #dcfae6; color: #085d3a; }
.i { background: #d1e9ff; color: #1849a9; }
.f { background: #fef0c7; color: #93370d; }

08. Compact Dot Timeline

MinimalSidebar

A narrow timeline for sidebars and cards: small dots, short labels and times aligned in a grid. It packs a lot of history into little space, and the latest item is emphasised with a brighter dot and text.

View code
<ol class="tl8">
  <li class="now"><span>Reply from support</span><time datetime="2026-10-04T11:00">11:00</time></li>
  <li><span>Ticket assigned to Kim</span><time datetime="2026-10-04T10:42">10:42</time></li>
  <li><span>Ticket opened</span><time datetime="2026-10-04T10:30">10:30</time></li>
</ol>
.tl8 { box-sizing: border-box; max-width: 100%; width: 300px; margin: 0; padding: 0; list-style: none; font: 13.5px Inter, system-ui, sans-serif; }
.tl8 li { position: relative; display: flex; justify-content: space-between; gap: 12px; padding: 0 0 14px 20px; color: #aab3c7; }
.tl8 li::before { content: ""; position: absolute; left: 0; top: 5px; width: 8px; height: 8px; border-radius: 50%; background: #4a5368; }
.tl8 li:not(:last-child)::after { content: ""; position: absolute; left: 3px; top: 15px; bottom: 0; width: 2px; background: #262d3e; }
.tl8 .now { color: #fff; font-weight: 600; }
.tl8 .now::before { background: #34d399; box-shadow: 0 0 0 3px rgba(52,211,153,.25); }
.tl8 time { color: #9aa4b8; font-variant-numeric: tabular-nums; }

About these CSS Timelines

Ordered lists and time elements

A timeline is an ordered list, because the order matters. Put dates in <time datetime="..."> so they are machine-readable as well as readable.

Lines and dots

The line is a border or a pseudo-element on the list, and each dot is a pseudo-element on its item, so the HTML stays a plain list.

Alternating layouts

Use grid placement and :nth-child to alternate sides on wide screens, keeping the source order chronological, then collapse to one column on phones.

Horizontal scrolling

A horizontal roadmap can scroll sideways with scroll snapping; make the scroll area focusable so keyboard users can scroll it too.

Frequently asked questions

Do timelines need JavaScript?

None of these do.

How do I show progress in a roadmap?

Write the status in text, such as Done or In progress, and use colour as a second cue.

Should newest be first?

For activity logs and changelogs, yes. For histories, oldest first usually reads better.