Back to CSS Radio Buttons Wave Fill Pure CSS
Share
HTML
<fieldset class="crb-wave">
  <legend class="crb-sr">Volume</legend>
  <label><input type="radio" name="crb-wave" /><span></span>Low</label>
  <label><input type="radio" name="crb-wave" checked /><span></span>Mid</label>
  <label><input type="radio" name="crb-wave" /><span></span>Loud</label>
</fieldset>
CSS
.crb-wave { display: flex; flex-direction: column; gap: 10px; border: 0; padding: 0; }
.crb-wave label {
  display: flex; align-items: center; gap: 10px;
  font: 500 13px/1 system-ui, sans-serif; color: #cbd5e1; cursor: pointer;
}
.crb-wave input { appearance: none; -webkit-appearance: none; position: absolute; opacity: 0; }
.crb-wave span {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid #444461;
  position: relative; overflow: hidden;
  background: transparent;
  transition: border-color 0.25s;
}
.crb-wave span::before {
  content: ''; position: absolute;
  top: 100%; left: -50%; width: 200%; height: 200%;
  background: radial-gradient(ellipse at top, transparent 40%, #06b6d4 41%);
  transition: top 0.5s ease-out;
}
.crb-wave input:checked + span { border-color: #06b6d4; }
.crb-wave input:checked + span::before {
  top: -10%;
  animation: crb-wave-bob 1.4s ease-in-out infinite;
}
@keyframes crb-wave-bob {
  0%,100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}

@media (prefers-reduced-motion: reduce) {
  .crb-wave,
  .crb-wave * {
    animation: none !important;
  }
}

.crb-sr {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}