Back to CSS Timelines Accordion Timeline Pure CSS + tiny JS
Share
HTML
<div class="tl8-wrap">
  <div class="tl8-row tl8-open">
    <div class="tl8-head" onclick="toggleTl2(this)">
      <span class="tl8-year">1998</span>
      <span class="tl8-summary">Data Protection Act <span class="tl8-badge tl8-badge-en">Enacted</span></span>
      <span class="tl8-arrow" aria-hidden="true">▾</span>
    </div>
    <div class="tl8-body">
      <div class="tl8-body-inner">
        <div class="tl8-detail">
          <p class="tl8-detail-label">Jurisdiction</p>
          <p class="tl8-detail-text">United Kingdom. Replaced the 1984 Act. Implemented the EC Data Protection Directive 95/46/EC into domestic law.</p>
        </div>
        <div class="tl8-detail">
          <p class="tl8-detail-label">Key Provisions</p>
          <p class="tl8-detail-text">Eight data protection principles governing fair processing, purpose limitation, data accuracy, and subject access rights.</p>
        </div>
      </div>
    </div>
  </div>

  <div class="tl8-row">
    <div class="tl8-head" onclick="toggleTl2(this)">
      <span class="tl8-year">2002</span>
      <span class="tl8-summary">Privacy &amp; Electronic Comms <span class="tl8-badge tl8-badge-en">Enacted</span></span>
      <span class="tl8-arrow" aria-hidden="true">▾</span>
    </div>
    <div class="tl8-body">
      <div class="tl8-body-inner">
        <div class="tl8-detail">
          <p class="tl8-detail-label">Scope</p>
          <p class="tl8-detail-text">Regulated direct marketing, cookies, and electronic communications. First major regulation to address unsolicited email.</p>
        </div>
        <div class="tl8-detail">
          <p class="tl8-detail-label">Amendment (2011)</p>
          <p class="tl8-detail-text">Cookie consent requirements strengthened following EU pressure. Opt-in became mandatory for non-essential tracking.</p>
        </div>
      </div>
    </div>
  </div>

  <div class="tl8-row">
    <div class="tl8-head" onclick="toggleTl2(this)">
      <span class="tl8-year">2018</span>
      <span class="tl8-summary">GDPR / DPA 2018 <span class="tl8-badge tl8-badge-en">Enacted</span></span>
      <span class="tl8-arrow" aria-hidden="true">▾</span>
    </div>
    <div class="tl8-body">
      <div class="tl8-body-inner">
        <div class="tl8-detail">
          <p class="tl8-detail-label">Scale</p>
          <p class="tl8-detail-text">EU-wide regulation with extraterritorial effect. Maximum fines of €20M or 4% of global annual turnover, whichever is higher.</p>
        </div>
        <div class="tl8-detail">
          <p class="tl8-detail-label">New Rights</p>
          <p class="tl8-detail-text">Right to erasure, data portability, and objection to automated decision-making formally enshrined for the first time.</p>
        </div>
      </div>
    </div>
  </div>

  <div class="tl8-row">
    <div class="tl8-head" onclick="toggleTl2(this)">
      <span class="tl8-year">2022</span>
      <span class="tl8-summary">UK GDPR Post-Brexit <span class="tl8-badge tl8-badge-am">Amended</span></span>
      <span class="tl8-arrow" aria-hidden="true">▾</span>
    </div>
    <div class="tl8-body">
      <div class="tl8-body-inner">
        <div class="tl8-detail">
          <p class="tl8-detail-label">Divergence</p>
          <p class="tl8-detail-text">UK retained GDPR principles but began diverging from EU text. Government proposed reforms to reduce compliance burden for SMEs.</p>
        </div>
        <div class="tl8-detail">
          <p class="tl8-detail-label">Adequacy Decision</p>
          <p class="tl8-detail-text">EU granted UK adequacy status until 2025, permitting data flows. Subject to ongoing review as UK law evolves independently.</p>
        </div>
      </div>
    </div>
  </div>
</div>
CSS
.tl8-wrap {
  --tl8-bg: #faf7f2;
  --tl8-a:  #b5451b;
  --tl8-ink: #1a1209;
  background: var(--tl8-bg);
  padding: 2rem 1.5rem;
  max-width: 780px;
  margin: 0 auto;
  font-family: 'Inter', system-ui, sans-serif;
  border-top: 2px solid var(--tl8-ink);
}
.tl8-row {
  border-bottom: 1px solid rgba(26,18,9,0.12);
}
.tl8-head {
  display: grid;
  grid-template-columns: 90px 1fr 28px;
  gap: 1.5rem;
  align-items: center;
  padding: 1.1rem 0;
  cursor: pointer;
  transition: padding 0.15s;
}
.tl8-head:hover {
  padding-left: 0.5rem;
}
.tl8-year {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--tl8-ink);
}
.tl8-summary {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 0.95rem;
  color: var(--tl8-ink);
}
.tl8-arrow {
  width: 28px;
  height: 28px;
  border: 1px solid rgba(26,18,9,0.25);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--tl8-ink);
  transition: transform 0.3s, background 0.2s, color 0.2s;
  flex-shrink: 0;
}
.tl8-row.tl8-open .tl8-arrow {
  transform: rotate(180deg);
  background: var(--tl8-ink);
  color: var(--tl8-bg);
}
.tl8-body {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.4s cubic-bezier(0.4,0,0.2,1);
}
.tl8-row.tl8-open .tl8-body {
  max-height: 400px;
}
.tl8-body-inner {
  padding: 0 0 1.5rem 6rem;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
}
.tl8-detail {
  background: #fff;
  border: 1px solid rgba(26,18,9,0.1);
  padding: 0.9rem 1rem;
  border-radius: 2px;
}
.tl8-detail-label {
  font-family: ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--tl8-a);
  margin-bottom: 0.4rem;
}
.tl8-detail-text {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 13.5px;
  color: rgba(26,18,9,0.65);
  line-height: 1.6;
}
.tl8-badge {
  display: inline-block;
  font-family: ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.5px;
  padding: 0.15rem 0.5rem;
  border-radius: 2px;
  margin-left: 0.5rem;
  vertical-align: middle;
}
.tl8-badge-en {
  background: rgba(27,67,50,0.12);
  color: #1b4332;
}
.tl8-badge-am {
  background: rgba(181,69,27,0.1);
  color: var(--tl8-a);
}
@media (max-width: 600px) {
  .tl8-head { grid-template-columns: 70px 1fr 28px; gap: 0.75rem; }
  .tl8-body-inner { padding-left: 0; grid-template-columns: 1fr; }
}
JS
// Click any year-row header to toggle that row open. Only one row
// stays open at a time — clicking another collapses the previous one.
// Wired via inline onclick="toggleTl2(this)" in the HTML markup.
function toggleTl2(headEl) {
  const row = headEl.closest('.tl8-row');
  const isOpen = row.classList.contains('tl8-open');
  document.querySelectorAll('.tl8-row.tl8-open').forEach(r => r.classList.remove('tl8-open'));
  if (!isOpen) row.classList.add('tl8-open');
}