AI CSS Animations

Retro Radio Preset Buttons

The original radio buttons: chunky preset keys on an old car stereo. Pressing one sinks it and pops the others back up, its LED lights and the display rolls to the station.

Also known as: car radio buttons css, 3d pressed radio buttons, vintage push button radio.

HTML

<div class="rad-retro-radio-presets" role="radiogroup" aria-label="Station preset">
  <div class="rad-retro-radio-presets-display" aria-hidden="true"><span>88.1</span><span>94.7</span><span>101.5</span><span>107.9</span></div>
  <div class="rad-retro-radio-presets-keys">
    <label><input type="radio" name="rad-retro-radio-presets" value="88.1" aria-label="Preset 1, 88.1" checked><span>1</span></label>
    <label><input type="radio" name="rad-retro-radio-presets" value="94.7" aria-label="Preset 2, 94.7"><span>2</span></label>
    <label><input type="radio" name="rad-retro-radio-presets" value="101.5" aria-label="Preset 3, 101.5"><span>3</span></label>
    <label><input type="radio" name="rad-retro-radio-presets" value="107.9" aria-label="Preset 4, 107.9"><span>4</span></label>
  </div>
</div>

CSS

.rad-retro-radio-presets {
  --c: var(--rad-color, #3b82f6);
  font-size: var(--rad-size, 18px);
  --i: 0;
  display: inline-grid;
  gap: 0.75em;
  padding: 0.8em 0.8em 0.7em;
  border-radius: 0.9em;
  background: linear-gradient(#3d424a, #22262c);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 0.6em 1.2em -0.5em rgba(0, 0, 0, 0.55);
  font-family: system-ui, sans-serif;
  line-height: 1.2;
}
.rad-retro-radio-presets:has(label:nth-of-type(2) :checked) { --i: 1; }
.rad-retro-radio-presets:has(label:nth-of-type(3) :checked) { --i: 2; }
.rad-retro-radio-presets:has(label:nth-of-type(4) :checked) { --i: 3; }
.rad-retro-radio-presets-display {
  position: relative;
  height: 2.1em;
  overflow: hidden;
  border-radius: 0.4em;
  background: #0d1411;
  box-shadow: inset 0 0.12em 0.35em rgba(0, 0, 0, 0.7);
  color: var(--c);
  font: 700 1.2em/1.75em ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.08em;
  text-shadow: 0 0 0.45em color-mix(in srgb, var(--c) 80%, transparent);
}
.rad-retro-radio-presets-display::before {
  content: "FM";
  position: absolute;
  left: 0.9em;
  font-size: 0.55em;
  line-height: 3.18em;
  opacity: 0.75;
}
.rad-retro-radio-presets-display span {
  display: block;
  padding-right: 0.6em;
  text-align: right;
  transform: translateY(calc(var(--i) * -100%));
  transition: transform 0.45s cubic-bezier(0.65, 0, 0.35, 1);
}
.rad-retro-radio-presets-keys {
  display: flex;
  gap: 0.45em;
  padding-top: 0.35em;
}
.rad-retro-radio-presets label {
  position: relative;
  border-radius: 0.45em;
  background: #968c75;
  box-shadow: 0 0.15em 0.3em rgba(0, 0, 0, 0.55);
  cursor: pointer;
}
.rad-retro-radio-presets input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}
.rad-retro-radio-presets input + span {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.9em;
  height: 2.3em;
  border-radius: 0.45em;
  background: linear-gradient(#f5f0e3, #d9d0bb);
  box-shadow: inset 0 1px 0 #fff;
  color: #45413a;
  font-size: 1.05em;
  font-weight: 800;
  transform: translateY(-0.34em);
  transition: transform 0.22s cubic-bezier(0.3, 1.8, 0.5, 1), filter 0.2s ease;
}
.rad-retro-radio-presets input + span::before {
  content: "";
  position: absolute;
  top: 0.28em;
  width: 0.9em;
  height: 0.16em;
  border-radius: 0.1em;
  background: #b6ad97;
  transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
.rad-retro-radio-presets label:hover input:not(:checked) + span {
  filter: brightness(1.04);
  transform: translateY(-0.26em);
}
.rad-retro-radio-presets input:checked + span {
  filter: brightness(0.93);
  transform: translateY(-0.04em);
  transition: transform 0.08s ease-in, filter 0.1s ease;
}
.rad-retro-radio-presets input:checked + span::before {
  background: var(--c);
  box-shadow: 0 0 0.35em var(--c);
}
.rad-retro-radio-presets input:focus-visible + span {
  outline: 0.12em solid var(--c);
  outline-offset: 0.18em;
}

@media (prefers-reduced-motion: reduce) {
  .rad-retro-radio-presets, .rad-retro-radio-presets *, .rad-retro-radio-presets::before, .rad-retro-radio-presets::after, .rad-retro-radio-presets *::before, .rad-retro-radio-presets *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --rad-color on the element or a parent. Currently previewing #3b82f6.
  • Size: set --rad-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 18px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar radio buttons