Skeleton

스켈레톤

Gray blocks that mimic the shape of content that hasn't arrived yet, shown while it loads.

Also known as: Skeleton screenContent placeholderGhost loading
···
html
<div class="skw" aria-hidden="true">
  <div class="sk-row">
    <div class="sk sk-avatar"></div>
    <div class="sk-lines"><div class="sk sk-line" style="width:70%"></div><div class="sk sk-line" style="width:45%"></div></div>
  </div>
  <div class="sk sk-block"></div>
</div>
css
.skw{width:min(230px,90%);display:grid;gap:12px}
.sk-row{display:flex;gap:10px;align-items:center}
.sk-lines{flex:1;display:grid;gap:7px}
.sk{border-radius:6px;background:linear-gradient(100deg,var(--line) 30%,color-mix(in srgb, var(--line) 40%, var(--surface)) 50%,var(--line) 70%);
  background-size:200% 100%;animation:shimmer 1.4s ease-in-out infinite}
.sk-avatar{width:40px;height:40px;border-radius:50%;flex-shrink:0}
.sk-line{height:9px}
.sk-block{height:44px;border-radius:9px}
@keyframes shimmer{0%{background-position:120% 0}100%{background-position:-20% 0}}

Draw gray blocks matching the size and position of the real content, then swap in the actual content without moving anything once data arrives. That reduces sudden layout shift and, unlike a blank screen, lets people predict something is about to appear — which feels faster.

The difference from a spinner was covered above: a spinner only announces "loading," while a skeleton previews the future shape of the content. The soft left-to-right shimmer is made by animating a CSS gradient's background-position.

From an accessibility angle, the skeleton blocks themselves don't need to be read by a screen reader — mark them aria-hidden="true" — and announce the start/end of loading through a separate aria-live region instead.