26 CSS Accordions — Vertical & Horizontal

Circular Arc

A four-segment ring menu — labels follow each arc via SVG textPath. Selected arc lights up with its theme color, the hub shows the active step number, and the body reveals a matching description.

Pure CSS MIT licensed

Circular Arc the 19th of 26 designs in the 26 CSS Accordions — Vertical & Horizontal collection. The design is implemented in pure CSS — no JavaScript required. Copy the HTML and CSS panels below into your project. Because the demo is pure CSS, it works in any framework or templating engine you happen to use. The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.

Live preview

Open in playground

The code

<div class="acc-arc">
  <input type="radio" name="arc" id="arc-1" checked />
  <input type="radio" name="arc" id="arc-2" />
  <input type="radio" name="arc" id="arc-3" />
  <input type="radio" name="arc" id="arc-4" />
  <div class="acc-arc__wheel">
    <svg viewBox="0 0 140 140" class="acc-arc__svg" aria-hidden="true">
      <!-- Annular wedges aligned to cardinals: each spans ±45° around N/E/S/W.
           Outer r=66, inner r=42, center (70,70). -->
      <path
        class="acc-arc__seg"
        data-i="0"
        d="M 23.33 23.33 A 66 66 0 0 1 116.67 23.33 L 99.7 40.3  A 42 42 0 0 0 40.3 40.3   Z"
      />
      <path
        class="acc-arc__seg"
        data-i="1"
        d="M 116.67 23.33 A 66 66 0 0 1 116.67 116.67 L 99.7 99.7  A 42 42 0 0 0 99.7 40.3  Z"
      />
      <path
        class="acc-arc__seg"
        data-i="2"
        d="M 116.67 116.67 A 66 66 0 0 1 23.33 116.67 L 40.3 99.7  A 42 42 0 0 0 99.7 99.7  Z"
      />
      <path
        class="acc-arc__seg"
        data-i="3"
        d="M 23.33 116.67 A 66 66 0 0 1 23.33 23.33 L 40.3 40.3   A 42 42 0 0 0 40.3 99.7  Z"
      />
      <!-- Wedge centroid labels at radius 54 from center -->
      <text class="acc-arc__lbl" data-i="0" x="70" y="22" text-anchor="middle">DISCOVER</text>
      <text
        class="acc-arc__lbl"
        data-i="1"
        x="121"
        y="73"
        text-anchor="middle"
        transform="rotate(90 121 70)"
      >
        DEFINE
      </text>
      <text class="acc-arc__lbl" data-i="2" x="70" y="123" text-anchor="middle">DELIVER</text>
      <text
        class="acc-arc__lbl"
        data-i="3"
        x="19"
        y="73"
        text-anchor="middle"
        transform="rotate(-90 19 70)"
      >
        REFINE
      </text>
    </svg>
    <!-- Click targets: 4 wedge polygons matching the 4 SVG arcs (top, right, bottom, left) -->
    <label for="arc-1" class="acc-arc__hit acc-arc__hit--n" aria-label="Discover"></label>
    <label for="arc-2" class="acc-arc__hit acc-arc__hit--e" aria-label="Define"></label>
    <label for="arc-3" class="acc-arc__hit acc-arc__hit--s" aria-label="Deliver"></label>
    <label for="arc-4" class="acc-arc__hit acc-arc__hit--w" aria-label="Refine"></label>
    <div class="acc-arc__hub">
      <span data-i="0">01</span>
      <span data-i="1">02</span>
      <span data-i="2">03</span>
      <span data-i="3">04</span>
    </div>
  </div>
  <div class="acc-arc__body">
    <article data-i="0">
      <h4>Discover</h4>
      <p>Map the problem space. Talk to users. Sketch hypotheses before committing to a build.</p>
    </article>
    <article data-i="1">
      <h4>Define</h4>
      <p>Pick one bet. Frame it crisply. Write down what success actually looks like.</p>
    </article>
    <article data-i="2">
      <h4>Deliver</h4>
      <p>Ship a thin slice end-to-end. Measure real usage. Decide what comes next from data.</p>
    </article>
    <article data-i="3">
      <h4>Refine</h4>
      <p>
        Iterate on real signal, not imagined feedback. Compound the wins, drop what didn't earn its
        place.
      </p>
    </article>
  </div>
</div>
.acc-arc {
  display: grid; grid-template-columns: 150px 1fr; gap: 18px;
  height: 220px; align-items: center; padding: 6px 4px;
}
.acc-arc > input { position: absolute; opacity: 0; pointer-events: none; }
.acc-arc__wheel {
  position: relative; width: 150px; height: 150px; flex-shrink: 0;
}
.acc-arc__svg { width: 100%; height: 100%; display: block; }
.acc-arc__seg {
  fill: rgba(240,238,255,0.05);
  stroke: rgba(240,238,255,0.1); stroke-width: 1;
  transition: fill .3s, stroke .3s, stroke-width .3s;
}
.acc-arc__seg[data-i="0"] { fill: rgba(156,123,214,0.2); }
.acc-arc__seg[data-i="1"] { fill: rgba(212,154,92,0.2); }
.acc-arc__seg[data-i="2"] { fill: rgba(143,179,163,0.2); }
.acc-arc__seg[data-i="3"] { fill: rgba(200,162,200,0.2); }
.acc-arc__lbl {
  font: 700 9px/1 system-ui, sans-serif;
  letter-spacing: 0.18em; fill: rgba(240,238,255,0.6);
  transition: fill .25s;
}
/* Click hit targets — 4 explicit triangular wedges from center to outer edge.
   Each polygon: center (50%,50%), outer corner A, outer corner B */
.acc-arc__hit { position: absolute; inset: 0; cursor: pointer; }
.acc-arc__hit--n { clip-path: polygon(50% 50%, 100% 0,   0    0); }
.acc-arc__hit--e { clip-path: polygon(50% 50%, 100% 100%, 100% 0); }
.acc-arc__hit--s { clip-path: polygon(50% 50%, 0    100%, 100% 100%); }
.acc-arc__hit--w { clip-path: polygon(50% 50%, 0    0,    0    100%); }
.acc-arc__hub {
  position: absolute; left: 50%; top: 50%;
  width: 60px; height: 60px; border-radius: 50%;
  background: #1a1a24;
  box-shadow: 0 0 0 1px rgba(240,238,255,0.1), 0 6px 16px rgba(0,0,0,0.4);
  transform: translate(-50%, -50%);
  display: grid; place-items: center;
  pointer-events: none;
}
.acc-arc__hub span {
  grid-area: 1/1; font: 800 18px ui-monospace, monospace;
  color: #f0eeff; opacity: 0;
  transition: opacity .25s, color .25s;
}
.acc-arc__body { position: relative; height: 150px; }
.acc-arc__body article {
  position: absolute; inset: 0; margin: 0;
  padding: 0 0 0 14px;
  border-left: 2px solid rgba(240,238,255,0.08);
  display: flex; flex-direction: column; justify-content: center; gap: 6px;
  opacity: 0; transform: translateX(6px);
  transition: opacity .3s, transform .3s, border-color .3s;
}
.acc-arc__body h4 {
  margin: 0; font: 700 14px/1.2 system-ui, sans-serif;
  letter-spacing: 0.02em; color: #f0eeff;
}
.acc-arc__body p {
  margin: 0; font: 12px/1.6 system-ui, sans-serif;
  color: rgba(240,238,255,0.7);
}
/* Active states — explicit per-arc */
#arc-1:checked ~ .acc-arc__wheel .acc-arc__seg[data-i="0"] { fill: #9c7bd6; stroke: rgba(255,255,255,0.4); stroke-width: 1.5; }
#arc-2:checked ~ .acc-arc__wheel .acc-arc__seg[data-i="1"] { fill: #d49a5c; stroke: rgba(255,255,255,0.4); stroke-width: 1.5; }
#arc-3:checked ~ .acc-arc__wheel .acc-arc__seg[data-i="2"] { fill: #8fb3a3; stroke: rgba(255,255,255,0.4); stroke-width: 1.5; }
#arc-4:checked ~ .acc-arc__wheel .acc-arc__seg[data-i="3"] { fill: #c8a2c8; stroke: rgba(255,255,255,0.4); stroke-width: 1.5; }
#arc-1:checked ~ .acc-arc__wheel .acc-arc__lbl[data-i="0"],
#arc-2:checked ~ .acc-arc__wheel .acc-arc__lbl[data-i="1"],
#arc-3:checked ~ .acc-arc__wheel .acc-arc__lbl[data-i="2"],
#arc-4:checked ~ .acc-arc__wheel .acc-arc__lbl[data-i="3"] { fill: #15151d; }
#arc-1:checked ~ .acc-arc__wheel .acc-arc__hub span[data-i="0"] { opacity: 1; color: #b896e8; }
#arc-2:checked ~ .acc-arc__wheel .acc-arc__hub span[data-i="1"] { opacity: 1; color: #d49a5c; }
#arc-3:checked ~ .acc-arc__wheel .acc-arc__hub span[data-i="2"] { opacity: 1; color: #8fb3a3; }
#arc-4:checked ~ .acc-arc__wheel .acc-arc__hub span[data-i="3"] { opacity: 1; color: #c8a2c8; }
#arc-1:checked ~ .acc-arc__body article[data-i="0"],
#arc-2:checked ~ .acc-arc__body article[data-i="1"],
#arc-3:checked ~ .acc-arc__body article[data-i="2"],
#arc-4:checked ~ .acc-arc__body article[data-i="3"] {
  opacity: 1; transform: translateX(0);
}
#arc-1:checked ~ .acc-arc__body article[data-i="0"] { border-left-color: #9c7bd6; }
#arc-2:checked ~ .acc-arc__body article[data-i="1"] { border-left-color: #d49a5c; }
#arc-3:checked ~ .acc-arc__body article[data-i="2"] { border-left-color: #8fb3a3; }
#arc-4:checked ~ .acc-arc__body article[data-i="3"] { border-left-color: #c8a2c8; }

Search CodeFronts

Loading…