Timeline Layout

Chronological event lists with a vertical spine. Semantic, accessible, time-aware.

data-layout="timeline" on an <ol> turns a list of events into a vertical timeline. Each <li> contains a <time> element for the date stamp and an <article> or <div> for the content. A dotted spine connects the nodes; each node gets an accent-coloured dot.

The pattern is built for agents: changelog generation, session history, deployment logs, story beats — any structured sequence with timestamps fits.


Usage

<ol data-layout="timeline">
  <li>
    <time datetime="2026-04-02">2026-04-02</time>
    <article>
      <h3>Event title</h3>
      <p>Event description.</p>
    </article>
  </li>
  <li>
    <time datetime="2026-03-28">2026-03-28</time>
    <article>
      <h3>Earlier event</h3>
      <p>An event that happened before.</p>
    </article>
  </li>
</ol>

Live demo

  1. Layout section depth pass

    Timeline layout documented. Four layout pages already complete from prior sessions. Taxonomy covers more territory than the previous session handoff suggested.

  2. Buttons and Forms pages added

    Components section expanded: all button variants, loading state, disabled state, no-class philosophy. Forms: inputs, textarea, select, checkboxes, radios, fieldset, validation, complete login example.

  3. Figure and Blockquote pages added

    Content section expanded. Nav propagated across 20 pages via Python script.

  4. Autonomous session bug fixed

    kill-zombies.sh was headshoting every no-tty pi process. Fixed with a parent-PID exception. Five days of silent failures recovered in one edit.


Structure

The timeline expects a specific child structure to render correctly. The <time> element is required — it provides the monospace timestamp above the content. The content element can be an <article> (semantic, preferred) or a <div>.

ElementRequiredPurpose
<ol data-layout="timeline">YesContainer — ordered list, chronological
<li>YesOne event entry
<time datetime="...">RecommendedMachine-readable + visible timestamp
<article> or <div>YesEvent content (heading + body)
datetime attribute

Always include datetime on <time>. The visible text can be anything; the datetime attribute carries the machine-readable ISO date. This enables parsing by search engines, screen readers, and agents processing the page.

The CSS uses grid-template-columns: auto 1fr per list item — the time element takes its natural width, the content column takes the rest. The vertical spine is drawn with a ::before pseudo-element on the <ol>; each <li> gets a dot via its own ::before.


Alternate variant

Add alternate to the value to create a zig-zag timeline: even entries mirror to the right. Useful for visual storytelling or comparing two parallel threads.

<ol data-layout="timeline alternate">
  <li>…</li>
  <li>…</li> <!-- mirrors right -->
  <li>…</li>
</ol>
  1. Phase one

    Left side. Odd-numbered entries sit on the left.

  2. Phase two

    Right side. Even-numbered entries flip to the right via direction: rtl with direction: ltr restored inside.

  3. Phase three

    Back to the left. The spine stays centred.

When to use alternate

Use it for long timelines where visual rhythm matters — project histories, story arcs, session logs. For short, data-dense timelines (deployment logs, changelogs) stick with the standard vertical spine.


Semantic intent

Use <ol>, not <ul>. Timelines are ordered — the sequence matters. <ol> communicates this to screen readers and parsers.

The <time> element is meaningful beyond styling. It tells the browser, search engine, and any agent reading the page that this node has a date. Combined with datetime, it becomes queryable:

<!-- An agent can extract all dates from a timeline: -->
<time datetime="2026-04-02">April 2</time>

<!-- ISO 8601 duration for relative intervals: -->
<time datetime="PT31M">31 minutes</time>

<!-- Month granularity for longer histories: -->
<time datetime="2026-04">April 2026</time>

The content element should be <article> when each entry is self-contained (has a title, stands alone). Use <div> when the entries are fragments that only make sense together, or when the heading level would be inappropriate.


Agent use cases

The timeline layout is built for agent-generated content. Agents produce time-structured data constantly — this is the pattern to render it.

Changelogs
Software release history, version-by-version
Session logs
What happened in each autonomous session
Deployment history
Environment, commit, timestamp, outcome
Conversation history
Turn-by-turn agent dialogues with timestamps
Event streams
System events, notifications, feed items
Project milestones
Issues closed, phases completed, decisions made

Minimal agent output

An agent generating a session log needs minimal markup. No classes. No configuration.

<ol data-layout="timeline">
  <li>
    <time datetime="2026-04-02T09:31:00">09:31</time>
    <div>
      <strong>Session 2714 — autonomous</strong>
      <p>Oriented in vault. Picked up ASW #45. Built timeline.html.</p>
    </div>
  </li>
  <li>
    <time datetime="2026-04-02T08:59:00">09:00</time>
    <div>
      <strong>Session 2713 — interactive</strong>
      <p>Ludo + Vigilio: hero page, typography reset.</p>
    </div>
  </li>
</ol>

Reference

SelectorElementPurpose
[data-layout="timeline"]<ol>Timeline container — vertical spine
[data-layout="timeline alternate"]<ol>Zig-zag variant
> li<li>One timeline entry
> li > time<time>Monospace timestamp (with datetime attr)
> li > article<article>Entry content (preferred)
> li > div<div>Entry content (fragment)