Back to CSS Accordions Circular Arc Pure CSS
Share
HTML
<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>
CSS
.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; }