Back to CSS Toggles & Switches Waveform Toggle Pure CSS
Share
HTML
<label class="tg-wav">
  <input class="tg-wav-input" type="checkbox" checked>
  <span class="tg-wav-body" aria-hidden="true">
    <span class="tg-wav-bars">
      <span></span><span></span><span></span><span></span><span></span>
      <span></span><span></span><span></span><span></span>
    </span>
    <span class="tg-wav-text">Microphone</span>
    <span class="tg-wav-dot"></span>
  </span>
</label>
CSS
.tg-wav {
  --tg-wav-rim: #14141e;
  --tg-wav-wire: #1e1e2e;
  --tg-wav-fog: #3a3a52;
  --tg-wav-ash: #7a7a98;
  --tg-wav-ice: #00e5ff;
  display: inline-block;
  cursor: pointer;
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  font-size: 14px;
  user-select: none;
}
.tg-wav-input {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}
.tg-wav-body {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--tg-wav-rim);
  border: 1px solid var(--tg-wav-wire);
  min-width: 240px;
  transition: border-color 0.3s ease, background 0.3s ease;
}
.tg-wav-bars {
  display: flex;
  align-items: center;
  gap: 2.5px;
  height: 28px;
}
.tg-wav-bars span {
  display: block;
  width: 3px;
  border-radius: 2px;
  background: var(--tg-wav-fog);
  transition: background 0.3s ease, height 0.3s ease;
}
/* Static heights (off state) — each bar has its own resting height. */
.tg-wav-bars span:nth-child(1) { height: 8px; }
.tg-wav-bars span:nth-child(2) { height: 14px; }
.tg-wav-bars span:nth-child(3) { height: 20px; }
.tg-wav-bars span:nth-child(4) { height: 26px; }
.tg-wav-bars span:nth-child(5) { height: 18px; }
.tg-wav-bars span:nth-child(6) { height: 24px; }
.tg-wav-bars span:nth-child(7) { height: 12px; }
.tg-wav-bars span:nth-child(8) { height: 20px; }
.tg-wav-bars span:nth-child(9) { height: 8px; }
.tg-wav-text {
  font-size: 13px;
  color: var(--tg-wav-ash);
  transition: color 0.3s ease;
}
.tg-wav-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--tg-wav-wire);
  margin-left: auto;
  flex-shrink: 0;
  transition: background 0.3s ease, box-shadow 0.3s ease;
}
/* Each bar oscillates between its resting height and ~30% of it. The
   varied durations + delays keep the pattern from looking robotic. */
@keyframes tg-wav-breathe {
  0%, 100% { height: var(--tg-wav-h); }
  50%      { height: calc(var(--tg-wav-h) * 0.3 + 4px); }
}
.tg-wav-input:checked ~ .tg-wav-body {
  border-color: rgba(0,229,255,0.3);
  background: rgba(0,229,255,0.04);
}
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span {
  background: var(--tg-wav-ice);
}
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(1) { animation: tg-wav-breathe 0.9s ease-in-out infinite;       --tg-wav-h: 8px;  }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(2) { animation: tg-wav-breathe 0.7s ease-in-out 0.1s infinite;  --tg-wav-h: 14px; }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(3) { animation: tg-wav-breathe 1.1s ease-in-out 0.2s infinite;  --tg-wav-h: 20px; }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(4) { animation: tg-wav-breathe 0.8s ease-in-out 0.05s infinite; --tg-wav-h: 26px; }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(5) { animation: tg-wav-breathe 1.0s ease-in-out 0.15s infinite; --tg-wav-h: 18px; }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(6) { animation: tg-wav-breathe 0.6s ease-in-out 0.25s infinite; --tg-wav-h: 24px; }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(7) { animation: tg-wav-breathe 0.9s ease-in-out 0.08s infinite; --tg-wav-h: 12px; }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(8) { animation: tg-wav-breathe 1.2s ease-in-out 0.18s infinite; --tg-wav-h: 20px; }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span:nth-child(9) { animation: tg-wav-breathe 0.75s ease-in-out 0.3s infinite; --tg-wav-h: 8px;  }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-text { color: var(--tg-wav-ice); }
.tg-wav-input:checked ~ .tg-wav-body .tg-wav-dot {
  background: var(--tg-wav-ice);
  box-shadow: 0 0 8px var(--tg-wav-ice);
}
.tg-wav-input:focus-visible ~ .tg-wav-body {
  outline: 2px solid var(--tg-wav-ice);
  outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
  .tg-wav-body,
  .tg-wav-bars span,
  .tg-wav-dot,
  .tg-wav-text { transition: none; }
  .tg-wav-input:checked ~ .tg-wav-body .tg-wav-bars span { animation: none; }
}