Pulse Loader

펄스 로더

A single dot that grows and fades on repeat, like a heartbeat signaling the system is still alive.

Also known as: Pulsing dot
···
html
<div class="wrap" role="status" aria-live="polite">
  <div class="pd" aria-hidden="true"></div>
  <span class="cap">scale + opacity 펄스</span>
</div>
css
.wrap{display:flex;flex-direction:column;align-items:center;gap:18px}
.pd{width:clamp(22px,7vmin,38px);height:clamp(22px,7vmin,38px);border-radius:50%;background:var(--accent);animation:pl 1.3s ease-out infinite}
@keyframes pl{0%{transform:scale(.55);opacity:1}70%{opacity:.15}100%{transform:scale(1.5);opacity:0}}
.cap{font-size:clamp(9px,2.4vmin,11px);color:var(--muted);letter-spacing:.02em}

About as minimal as an indeterminate indicator gets — it says little more than "still alive" — which makes it a good quiet signal for a live connection state (websocket connected, recording in progress). It's the wrong choice once progress can be measured; use progress-ring for that.

A single dot animates scale and opacity together on an ease-out-leaning keyframe, producing a "grow and fade" feel. Being a one-dot implementation, it takes far less code than the others here, and lining up several dots naturally turns it into ripple-loader.

For a long wait covering the whole screen, a skeleton usually feels faster; for anything under 200ms, skip it entirely to avoid a flash. Give the wrapper role="status" and aria-live="polite", and hide the dot itself with aria-hidden="true" since it's decorative. Under prefers-reduced-motion, shrink the scale range or fall back to a static dot.