AI CSS Animations

Text to Speech Loader

A speaker icon with pulsing sound waves and a sentence whose highlight hops from word to word as it is read aloud. Every word shares one keyframe with a staggered delay.

Also known as: read aloud animation, tts word highlight, karaoke text highlight.

HTML

<div class="ldr-text-to-speech" role="status" aria-label="Reading aloud">
  <svg class="ldr-text-to-speech-icon" viewBox="0 0 24 24" aria-hidden="true"><path class="ldr-text-to-speech-body" d="M4 9.5h3.5L12 5.5v13l-4.5-4H4z"/><path class="ldr-text-to-speech-wave" d="M15.5 9.2a4 4 0 0 1 0 5.6"/><path class="ldr-text-to-speech-wave" d="M18.3 6.6a7.8 7.8 0 0 1 0 10.8"/></svg>
  <span class="ldr-text-to-speech-words" aria-hidden="true"><span>Reading</span> <span>your</span> <span>notes</span> <span>aloud</span></span>
</div>

CSS

.ldr-text-to-speech {
  --s: var(--ldr-size, 48px);
  --c: var(--ldr-color, #3b82f6);
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font: 500 calc(var(--s) / 3) / 1.5 system-ui, sans-serif;
  color: color-mix(in srgb, currentColor 72%, transparent);
  white-space: nowrap;
}
.ldr-text-to-speech-icon {
  width: 1.4em;
  height: 1.4em;
  fill: none;
  stroke: var(--c);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ldr-text-to-speech-body { fill: var(--c); }
.ldr-text-to-speech-wave {
  animation: ldr-text-to-speech-wave 0.9s ease-in-out infinite;
}
.ldr-text-to-speech-wave + .ldr-text-to-speech-wave { animation-delay: 0.15s; }
.ldr-text-to-speech-words span {
  padding: 0.1em 0.2em;
  margin: 0 -0.2em;
  border-radius: 0.35em;
  animation: ldr-text-to-speech-read 2s infinite;
}
.ldr-text-to-speech-words span:nth-child(2) { animation-delay: 0.5s; }
.ldr-text-to-speech-words span:nth-child(3) { animation-delay: 1s; }
.ldr-text-to-speech-words span:nth-child(4) { animation-delay: 1.5s; }
@keyframes ldr-text-to-speech-read {
  0%, 21%  { background-color: color-mix(in srgb, var(--ldr-color, #3b82f6) 20%, transparent); color: var(--c); }
  25%, 100% { background-color: transparent; color: inherit; }
}
@keyframes ldr-text-to-speech-wave {
  0%, 100% { opacity: 0.25; }
  50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .ldr-text-to-speech, .ldr-text-to-speech *, .ldr-text-to-speech::before, .ldr-text-to-speech::after, .ldr-text-to-speech *::before, .ldr-text-to-speech *::after {
    animation-duration: 3s;
  }
}

Customizing this loader

  • Color: set --ldr-color on the element or a parent. Currently previewing #3b82f6.
  • Size: set --ldr-size. Every dimension in the snippet is derived from it. Currently previewing 64px.
  • Speed: change the duration on the animation shorthand. Delays on the children are relative, so they keep their rhythm.
  • Accessibility: the root carries role="status" and an aria-label so screen readers announce the wait. The reduced-motion rule at the end slows the animation for users who asked for less motion.

Similar loaders