AI CSS Animations

Smart Speaker Listening Ring

A hairline isometric smart speaker wakes: an accent arc sweeps once round the light ring on its top face and settles on a spring. The grille is a field of dots on the cylinder's visible half.

Also known as: claude hairline, isometric smart speaker, voice assistant ring animation.

HTML

<div class="hln-speaker-ring" role="img" aria-label="A smart speaker with its light ring sweeping">
  <svg viewBox="-110 -60 220 120" aria-hidden="true">
    <g transform="translate(0 17.9) scale(1.15)">
      <g><path d="M-22.63,-30 V0 A22.63,11.31 0 0 0 22.63,0 V-30 Z"/><ellipse cx="0" cy="-30" rx="22.63" ry="11.31"/></g>
      <path class="hln-speaker-ring-l hln-speaker-ring-o" d="M-22.63,-3 A22.63,11.31 0 0 0 22.63,-3"/>
      <circle class="hln-speaker-ring-l" cx="22.35" cy="-4.23" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="20.91" cy="-1.67" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="18.31" cy="0.65" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="14.7" cy="2.6" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="10.27" cy="4.08" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="5.28" cy="5" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="0" cy="5.31" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-5.28" cy="5" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-10.27" cy="4.08" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-14.7" cy="2.6" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-18.31" cy="0.65" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-20.91" cy="-1.67" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-22.35" cy="-4.23" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="22.35" cy="-7.83" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="20.91" cy="-5.27" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="18.31" cy="-2.95" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="14.7" cy="-1" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="10.27" cy="0.48" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="5.28" cy="1.4" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="0" cy="1.71" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-5.28" cy="1.4" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-10.27" cy="0.48" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-14.7" cy="-1" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-18.31" cy="-2.95" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-20.91" cy="-5.27" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-22.35" cy="-7.83" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="22.35" cy="-11.43" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="20.91" cy="-8.87" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="18.31" cy="-6.55" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="14.7" cy="-4.6" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="10.27" cy="-3.12" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="5.28" cy="-2.2" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="0" cy="-1.89" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-5.28" cy="-2.2" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-10.27" cy="-3.12" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-14.7" cy="-4.6" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-18.31" cy="-6.55" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-20.91" cy="-8.87" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-22.35" cy="-11.43" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="22.35" cy="-15.03" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="20.91" cy="-12.47" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="18.31" cy="-10.15" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="14.7" cy="-8.2" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="10.27" cy="-6.72" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="5.28" cy="-5.8" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="0" cy="-5.49" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-5.28" cy="-5.8" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-10.27" cy="-6.72" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-14.7" cy="-8.2" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-18.31" cy="-10.15" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-20.91" cy="-12.47" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-22.35" cy="-15.03" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="22.35" cy="-18.63" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="20.91" cy="-16.07" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="18.31" cy="-13.75" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="14.7" cy="-11.8" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="10.27" cy="-10.32" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="5.28" cy="-9.4" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="0" cy="-9.09" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-5.28" cy="-9.4" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-10.27" cy="-10.32" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-14.7" cy="-11.8" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-18.31" cy="-13.75" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-20.91" cy="-16.07" r=".45"/>
      <circle class="hln-speaker-ring-l" cx="-22.35" cy="-18.63" r=".45"/>
      <g transform="matrix(1 .5 -1 .5 0 -30)"><circle class="hln-speaker-ring-l" cx="0" cy="0" r="12.6"/><circle class="hln-speaker-ring-l" cx="0" cy="0" r="10.8"/><circle class="hln-speaker-ring-l" cx="-3.5" cy="0" r="0.9"/><circle class="hln-speaker-ring-l" cx="3.5" cy="0" r="0.9"/><g class="hln-speaker-ring-sweep"><path class="hln-speaker-ring-a hln-speaker-ring-o" d="M9.66,-6.61 A11.7,11.7 0 0 1 9.66,6.61"/></g></g>
    </g>
  </svg>
</div>

CSS

.hln-speaker-ring {
  --c: var(--hln-color, #ff4f2e);
  font-size: var(--hln-size, 16px);
  position: relative;
  display: grid;
  place-items: center;
  width: 22em;
  height: 12em;
  border-radius: 0.75em;
  background: #f6f5f1;
  overflow: hidden;
}
.hln-speaker-ring svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: #ffffff;
  stroke: #1c1d21;
  stroke-width: 1.25;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.hln-speaker-ring svg * {
  vector-effect: non-scaling-stroke;
}
.hln-speaker-ring .hln-speaker-ring-o {
  fill: none;
}
.hln-speaker-ring .hln-speaker-ring-l {
  stroke: #9a9ca3;
}
.hln-speaker-ring .hln-speaker-ring-a {
  stroke: var(--c);
}
.hln-speaker-ring .hln-speaker-ring-sweep {
  animation: hln-speaker-ring-sweep 5s infinite;
}
@keyframes hln-speaker-ring-sweep {
  0% { transform: rotate(-120deg); opacity: 0; }
  8% { transform: rotate(-120deg); opacity: 0; }
  11% { transform: rotate(-90deg); opacity: 1; animation-timing-function: linear(0, 0.031, 0.107, 0.208, 0.321, 0.434, 0.541, 0.639, 0.724, 0.796, 0.855, 0.903, 0.94, 0.968, 0.988, 1.002, 1.011, 1.017, 1.019, 1.02, 1.019, 1.018, 1.016, 1.013, 1.011, 1.009, 1.007, 1.005, 1.004, 1.003, 1.002, 1.001, 1); }
  40% { transform: rotate(270deg); opacity: 1; }
  82% { transform: rotate(270deg); opacity: 1; animation-timing-function: cubic-bezier(.65,0,.35,1); }
  90% { transform: rotate(290deg); opacity: 0; }
  100% { transform: rotate(-120deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .hln-speaker-ring * {
    animation: none !important;
  }
}

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

Customizing this snippet

  • Color: set --hln-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --hln-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 16px.
  • 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 hairline animations