웨이브 바

Wave Bars

여러 개의 막대가 같은 리듬으로 높낮이를 이어가며, 물결처럼 흐르는 비확정적 로더.

다른 이름: Equalizer wave
···
html
<div class="wrap" role="status" aria-live="polite">
  <div class="wb" aria-hidden="true"><span></span><span></span><span></span><span></span><span></span></div>
  <span class="cap">scaleY 동일 주기 + 스태거</span>
</div>
css
.wrap{display:flex;flex-direction:column;align-items:center;gap:18px}
.wb{display:flex;align-items:center;gap:clamp(4px,1.4vmin,7px);height:clamp(30px,9vmin,52px)}
.wb span{width:clamp(6px,2vmin,10px);height:100%;border-radius:999px;background:var(--accent);animation:wv 1s ease-in-out infinite}
.wb span:nth-child(1){animation-delay:0s}
.wb span:nth-child(2){animation-delay:.12s}
.wb span:nth-child(3){animation-delay:.24s}
.wb span:nth-child(4){animation-delay:.36s}
.wb span:nth-child(5){animation-delay:.48s}
@keyframes wv{0%,100%{transform:scaleY(.3)}50%{transform:scaleY(1)}}
.cap{font-size:clamp(9px,2.4vmin,11px);color:var(--muted);letter-spacing:.02em}

막대라는 형태 때문에 오디오 재생·음성 인식 중임을 은유하는 자리에 자주 쓰이지만, 실제로 전달하는 정보는 다른 비확정적 로더와 같은 "처리 중"뿐입니다. 인식된 텍스트 길이나 녹음 시간처럼 셀 수 있는 값이 있다면 그 값을 텍스트로 함께 보여주는 편이 낫습니다.

막대 개수만큼 같은 scaleY keyframe(0.3배에서 1배로 커졌다 줄어듦)을 주고, 막대마다 animation-delay를 균등하게 어긋나게 줘서 한쪽 끝에서 시작한 움직임이 반대쪽 끝까지 이어지는 것처럼 보이게 합니다. 모든 막대의 지속시간이 같다는 점이 아래 equalizer-loader와의 차이입니다 — 그쪽은 막대마다 지속시간 자체가 다릅니다.

화면 대부분을 오래 가리는 로딩이면 스켈레톤을, 200ms 이내로 끝날 대기라면 생략을 고려하세요. role="status"·aria-live="polite"를 감싸는 요소에 주고 막대는 장식이므로 aria-hidden="true"로 숨깁니다. prefers-reduced-motion에서는 웨이브 진폭을 줄이거나 막대 높이를 고정값으로 대체할 수 있습니다.