32 CSS Accordions — Vertical & Horizontal
13 / 32

All 32 in 32 CSS Accordions — Vertical & Horizontal

  1. 01Pure CSS FAQ Accordion with <details> and <summary> (No JavaScript)
  2. 02Mobile Navigation Accordion Menu (CSS-Only Hamburger + Drill-Down)
  3. 03E-commerce Filter Sidebar Accordion with Exclusive Open (Product Filters)
  4. 04Nested Multi-Level Accordion (CSS Tree View for Docs & File Explorers)
  5. 05Smoothly Animated <details> Accordion — Transition height: auto in Pure CSS
  6. 06Exclusive Single-Open Accordion with the details name Attribute (Close Others Automatically)
  7. 07Underline Reveal Accordion — Editorial Minimal with Animated Rules
  8. 08Numbered Steps Accordion — Process Timeline for Onboarding Flows
  9. 09Plus / Minus Morph Accordion — CSS-Drawn Icon Animation
  10. 10Chevron Rotate Card Accordion — The Production Default, Perfected
  11. 11Brutalist Stamp Accordion — Bold Borders, Hard Shadows, Zero Subtlety
  12. 12Glassmorphism Frosted Accordion with backdrop-filter Blur
  13. 13Minimal Rail Accordion — Timeline Dot Spine for Changelogs & Roadmaps
  14. 14Card Lift Accordion — Elevation & Scale on Open (Material-Style Depth)
  15. 15Diagonal Slant Accordion — Skewed Parallelogram Headers
  16. 16Stepped Stair Accordion — Indented Cascade with Depth Levels
  17. 17Circular Dial Accordion — Conic-Gradient Progress Ring Toggles
  18. 18Marquee Header Accordion — Scrolling Ticker Titles on the Open Item
  19. 19Code Comment Accordion — Editor-Themed Collapsible Doc Blocks
  20. 20Paper Fold 3D Accordion — perspective + rotateX Unfolding Panels
  21. 21Equalizer Accordion — Animated Level Bars for Playlists & Audio
  22. 22Stacked Cards Deck Accordion — Overlapping Pull-Out Hand
  23. 23Holographic Slot Accordion — @property Rotating Border Sheen
  24. 24Aurora Drift Accordion — Dark Ambient Glow that Follows the Open Item
  25. 25Horizontal Strip Tabs Accordion — Vertical Text Columns with flex-grow
  26. 26Horizontal Image Reveal Accordion — Expanding Photo Gallery Panels
  27. 27Color Block Horizontal Accordion — Bold Flat Panels for Feature Sections
  28. 28Numbered Spine Horizontal Accordion — Editorial Magazine Index
  29. 29Curtain Slide Horizontal Accordion — clip-path Reveal Panels
  30. 30Vinyl Spine Horizontal Accordion — Record Shelf with Pull-Out Sleeves
  31. 31Cinema Reel Horizontal Accordion — Dark Letterboxed Showcase
  32. 32Aurora Strip Horizontal Accordion — Animated Gradient Glow Panels
Pure CSSMIT licensed

Minimal Rail Accordion — Timeline Dot Spine for Changelogs & Roadmaps

The quietest accordion in the set: a single hairline rail down the left with a dot per item — closed dots are hollow, the open dot fills and emits a soft ring pulse. Reads like a vertical timeline, which is exactly its use case: roadmaps, changelogs, order tracking and career pages.

Live Demo
Plain CSSTailwind v4
Try it

Build interactive UI like this from scratch: 20 HTML, CSS & JavaScript projects

ZTM · JavaScript Web Projects · 30‑day money-back guarantee · Affiliate link

10% off at checkout with code
Check ZTM Course

The code

<section class="acc-13" aria-label="Minimal rail timeline accordion demo">
  <div class="acc-13__wrap">
    <h3 class="acc-13__title">Roadmap</h3>
    <div class="acc-13__rail">
      <details class="acc-13__item" open>
        <summary class="acc-13__sum"><span class="acc-13__meta">Shipped · Q2 2026</span>Offline-first sync engine</summary>
        <div class="acc-13__body"><p>Every document now resolves conflicts with CRDTs locally — edits made on a plane merge cleanly when you land.</p></div>
      </details>
      <details class="acc-13__item">
        <summary class="acc-13__sum"><span class="acc-13__meta">In progress · Q3 2026</span>Shared workspaces</summary>
        <div class="acc-13__body"><p>Real-time cursors, granular roles and workspace-level templates. In beta with 40 design teams now.</p></div>
      </details>
      <details class="acc-13__item">
        <summary class="acc-13__sum"><span class="acc-13__meta">Planned · Q4 2026</span>Plugin API</summary>
        <div class="acc-13__body"><p>A sandboxed runtime with typed manifests. The first-party plugins (linear sync, figma import) will be open source.</p></div>
      </details>
      <details class="acc-13__item">
        <summary class="acc-13__sum"><span class="acc-13__meta">Exploring</span>On-prem deployment</summary>
        <div class="acc-13__body"><p>Single-tenant images with your KMS keys. Talk to us if your compliance team needs this sooner.</p></div>
      </details>
    </div>
  </div>
</section>
.acc-13,
.acc-13 *,
.acc-13 *::before,
.acc-13 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.acc-13 {
  --accent: oklch(0.58 0.16 250);
  --dot: 12px;
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fafbfd;
  padding: 48px 24px;
}

.acc-13__wrap {
  width: min(520px,100%);
}

.acc-13__title {
  font-size: 24px;
  font-weight: 800;
  color: #1a2030;
  letter-spacing: -.02em;
  margin-bottom: 22px;
}

.acc-13__rail {
  border-left: 1.5px solid #e2e6ef;
  padding-left: 28px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.acc-13__sum {
  list-style: none;
  position: relative;
  padding: 10px 0;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 16.5px;
  font-weight: 700;
  color: #232b40;
}

.acc-13__sum::-webkit-details-marker {
  display: none;
}

.acc-13__sum::marker {
  content: "";
}

.acc-13__sum::before {
  content: "";
  position: absolute;
  left: calc(-28px - var(--dot)/2 - .75px);
  top: 34px;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: #fafbfd;
  border: 2px solid #c6cdda;
  transition: background .25s,border-color .25s;
}

.acc-13__sum::after {
  content: "";
  position: absolute;
  left: calc(-28px - var(--dot)/2 - .75px);
  top: 34px;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0;
  pointer-events: none;
}

.acc-13__item[open] > .acc-13__sum::before {
  background: var(--accent);
  border-color: var(--accent);
}

.acc-13__item[open] > .acc-13__sum::after {
  animation: acc-13-pulse .7s ease-out;
}

@keyframes acc-13-pulse {
  from {
    opacity: .8;
    scale: 1;
  }

  to {
    opacity: 0;
    scale: 2.4;
  }
}

.acc-13__sum:hover {
  color: var(--accent);
}

.acc-13__meta {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: #98a1b6;
}

.acc-13__item[open] .acc-13__meta {
  color: var(--accent);
}

.acc-13__body {
  padding: 2px 12px 16px 0;
  font-size: 14.5px;
  line-height: 1.65;
  color: #4d5670;
}

.acc-13__item[open] .acc-13__body {
  animation: acc-13-in .35s ease-out;
}

@keyframes acc-13-in {
  from {
    opacity: 0;
    translate: 0 -5px;
  }

  to {
    opacity: 1;
    translate: 0 0;
  }
}

.acc-13__sum:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 8px;
}

@media (prefers-reduced-motion: reduce) {
  .acc-13__item[open] > .acc-13__sum::after {
    animation: none;
  }

  .acc-13__item[open] .acc-13__body {
    animation: none;
  }
}
/* No JavaScript — the rail is one border-left; each row's dot is its own ::before pulled onto the line, and details[open] fills the dot plus fires a single ring-pulse keyframe. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Accordions — Vertical & Horizontal from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Minimal Rail Accordion — Timeline Dot Spine for Changelogs & Roadmaps
Source: https://codefronts.com/navigation/css-accordions/minimal-rail/

The quietest accordion in the set: a single hairline rail down the left with a dot per item — closed dots are hollow, the open dot fills and emits a soft ring pulse. Reads like a vertical timeline, which is exactly its use case: roadmaps, changelogs, order tracking and career pages.
## HTML
```html
<section class="acc-13" aria-label="Minimal rail timeline accordion demo">
  <div class="acc-13__wrap">
    <h3 class="acc-13__title">Roadmap</h3>
    <div class="acc-13__rail">
      <details class="acc-13__item" open>
        <summary class="acc-13__sum"><span class="acc-13__meta">Shipped · Q2 2026</span>Offline-first sync engine</summary>
        <div class="acc-13__body"><p>Every document now resolves conflicts with CRDTs locally — edits made on a plane merge cleanly when you land.</p></div>
      </details>
      <details class="acc-13__item">
        <summary class="acc-13__sum"><span class="acc-13__meta">In progress · Q3 2026</span>Shared workspaces</summary>
        <div class="acc-13__body"><p>Real-time cursors, granular roles and workspace-level templates. In beta with 40 design teams now.</p></div>
      </details>
      <details class="acc-13__item">
        <summary class="acc-13__sum"><span class="acc-13__meta">Planned · Q4 2026</span>Plugin API</summary>
        <div class="acc-13__body"><p>A sandboxed runtime with typed manifests. The first-party plugins (linear sync, figma import) will be open source.</p></div>
      </details>
      <details class="acc-13__item">
        <summary class="acc-13__sum"><span class="acc-13__meta">Exploring</span>On-prem deployment</summary>
        <div class="acc-13__body"><p>Single-tenant images with your KMS keys. Talk to us if your compliance team needs this sooner.</p></div>
      </details>
    </div>
  </div>
</section>
```
## CSS
```css
.acc-13,
.acc-13 *,
.acc-13 *::before,
.acc-13 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.acc-13 {
  --accent: oklch(0.58 0.16 250);
  --dot: 12px;
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fafbfd;
  padding: 48px 24px;
}

.acc-13__wrap {
  width: min(520px,100%);
}

.acc-13__title {
  font-size: 24px;
  font-weight: 800;
  color: #1a2030;
  letter-spacing: -.02em;
  margin-bottom: 22px;
}

.acc-13__rail {
  border-left: 1.5px solid #e2e6ef;
  padding-left: 28px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.acc-13__sum {
  list-style: none;
  position: relative;
  padding: 10px 0;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 16.5px;
  font-weight: 700;
  color: #232b40;
}

.acc-13__sum::-webkit-details-marker {
  display: none;
}

.acc-13__sum::marker {
  content: "";
}

.acc-13__sum::before {
  content: "";
  position: absolute;
  left: calc(-28px - var(--dot)/2 - .75px);
  top: 34px;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: #fafbfd;
  border: 2px solid #c6cdda;
  transition: background .25s,border-color .25s;
}

.acc-13__sum::after {
  content: "";
  position: absolute;
  left: calc(-28px - var(--dot)/2 - .75px);
  top: 34px;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0;
  pointer-events: none;
}

.acc-13__item[open] > .acc-13__sum::before {
  background: var(--accent);
  border-color: var(--accent);
}

.acc-13__item[open] > .acc-13__sum::after {
  animation: acc-13-pulse .7s ease-out;
}

@keyframes acc-13-pulse {
  from {
    opacity: .8;
    scale: 1;
  }

  to {
    opacity: 0;
    scale: 2.4;
  }
}

.acc-13__sum:hover {
  color: var(--accent);
}

.acc-13__meta {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: #98a1b6;
}

.acc-13__item[open] .acc-13__meta {
  color: var(--accent);
}

.acc-13__body {
  padding: 2px 12px 16px 0;
  font-size: 14.5px;
  line-height: 1.65;
  color: #4d5670;
}

.acc-13__item[open] .acc-13__body {
  animation: acc-13-in .35s ease-out;
}

@keyframes acc-13-in {
  from {
    opacity: 0;
    translate: 0 -5px;
  }

  to {
    opacity: 1;
    translate: 0 0;
  }
}

.acc-13__sum:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 8px;
}

@media (prefers-reduced-motion: reduce) {
  .acc-13__item[open] > .acc-13__sum::after {
    animation: none;
  }

  .acc-13__item[open] .acc-13__body {
    animation: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — the rail is one border-left; each row's dot is its own ::before pulled onto the line, and details[open] fills the dot plus fires a single ring-pulse keyframe. */
```

How this works

The rail is a border-left on the list container — one element, no positioning math. Each summary places its dot with a ::before circle pulled left onto the rail via negative margin, so dots are guaranteed to sit ON the line at any font size or zoom level (they're positioned relative to their own row, not measured against the container).

The open dot fills accent and a second pseudo-element rings outward once (@keyframes scale + fade) — a single non-looping pulse, so the page stays calm at idle. Titles carry a date/meta line in small caps; open items reveal a short body. Everything else is whitespace: the demo shows how little an accordion needs when its structure (rail + dots) already communicates the model.

Techniques used: container border-left rail (zero positioning math) · row-relative ::before dots (zoom-proof alignment) · one-shot ring-pulse keyframe on open · hollow→filled dot state · small-caps meta line typography

Make it yours

  • Rail + dot geometry = --rail-x / --dot tokens.
  • Pulse: delete the ::after keyframe for total stillness.
  • Meta line (dates) is optional markup — remove for plain lists.
  • Invert to a right-side rail with border-right + flipped margins.

Gotchas — read before shipping

  • Position dots relative to their own row (::before + negative margin), never absolutely against the container — mixed content heights will misalign container-measured dots.
  • The ring pulse must be a ONE-SHOT animation (no infinite) — looping pulses on idle pages read as notification spam.
  • Keep at least 20px between rail and text or wrapped lines collide with dots.
  • A timeline implies chronology — don't use this skin for unordered FAQ content; users will read sequence into it.

Browser support

ChromeSafariFirefoxEdge
111+15.4+113+111+

Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome all.

Borders, pseudo-elements and one keyframe — baseline everywhere.

Techniques used in this demo

Search CodeFronts

Loading…