Flip Square

뒤집히는 정사각형

A square flipping around its axis on a steady beat — a rhythmic indeterminate loader.

Also known as: Cube flip loader
···
html
<div class="wrap" role="status" aria-live="polite">
  <div class="fscene" aria-hidden="true"><div class="fsq"></div></div>
  <span class="cap">perspective + rotateX/Y 스텝</span>
</div>
css
.wrap{display:flex;flex-direction:column;align-items:center;gap:18px}
.fscene{perspective:220px}
.fsq{width:clamp(28px,9vmin,50px);height:clamp(28px,9vmin,50px);background:linear-gradient(135deg,var(--accent),var(--accent-2));border-radius:6px;animation:flip 2.4s steps(1,end) infinite}
@keyframes flip{0%{transform:rotateX(0) rotateY(0)}25%{transform:rotateX(180deg) rotateY(0)}50%{transform:rotateX(180deg) rotateY(180deg)}75%{transform:rotateX(0) rotateY(180deg)}100%{transform:rotateX(0) rotateY(0)}}
.cap{font-size:clamp(9px,2.4vmin,11px);color:var(--muted);letter-spacing:.02em}

Where most rotating loaders feel like continuous spin, this one feels like a series of flips, giving it a clearer beat. It suits a spot where flipping is already the metaphor — a flashcard app, a brief pause right before a card-flip transition — and a plainer shape like a ring spinner is the safer default elsewhere.

A parent gets a perspective, and the square's keyframe alternates rotateX and rotateY by 90° at a time. Using steps() or sharp percentage boundaries instead of smooth ease keeps the "clunk, clunk" rhythm of a flip rather than a continuous spin.

A skeleton works better for a long wait covering the whole screen; skip it under 200ms. Give the wrapper role="status" and aria-live="polite", and hide the square with aria-hidden="true" since it's decorative. Under prefers-reduced-motion, swap the 3D rotation for a plain brightness change — perspective rotation can be especially uncomfortable for people sensitive to vestibular motion.