Bar Loader

바 로더

A short block sliding back and forth inside a track — a loader for a wait with no known progress.

Also known as: Sliding bar loader
···
html
<div class="wrap" role="status" aria-live="polite" aria-busy="true">
  <div class="track" aria-hidden="true"><div class="block"></div></div>
  <span class="cap">translateX 왕복</span>
</div>
css
.wrap{display:flex;flex-direction:column;align-items:center;gap:16px;width:min(76%,260px)}
.track{position:relative;width:100%;height:clamp(7px,2vmin,10px);border-radius:999px;background:var(--line);overflow:hidden}
.block{position:absolute;top:0;bottom:0;width:34%;border-radius:999px;background:var(--accent);animation:bl 1.4s ease-in-out infinite}
@keyframes bl{0%{left:0}50%{left:66%}100%{left:0}}
.cap{font-size:clamp(9px,2.4vmin,11px);color:var(--muted);letter-spacing:.02em}

An indeterminate "still working" cue for a wide, horizontal spot — the bottom of a card, the top of a page. The moment real progress becomes calculable, this loader has done its job; keep the same track shape but switch to the determinate progress-bar instead, which is more honest with the user.

Built with a track (a full-width gray bar) holding one shorter block, and a keyframe that oscillates translateX between 0% and the track's width with ease-in-out. Unlike indeterminate-bar below, there's only one block and it never stretches, which keeps the implementation simpler.

Skip it for loads under 200ms — it'll just flash — and prefer a skeleton for a long wait covering most of the screen. role="progressbar" is the wrong role when progress is unknown; wrap it with role="status" and aria-live="polite" instead, and put aria-busy="true" on the actual loading container. Under prefers-reduced-motion, you can tone the back-and-forth down to a faint pulse on the track.