Skeleton / Shimmer

Communicate loading progress with a low-contrast shimmer across placeholders.

Preview

Live preview

A placeholder with a moving sheen shown while content loads.

Preview
Authoritative vocabulary

Definition and close-term distinctions

English definitions are preserved verbatim from Animation Vocabulary; translations and distinctions help you choose precisely.

Canonical termskeleton-shimmer

Skeleton / Shimmer

骨架屏 / 微光
Authoritative definition

A placeholder with a moving sheen shown while content loads.

Chinese translation

内容加载期间显示的占位结构,表面带有移动的微光。

Browse all 91 terms
Design contract

Decide before this motion ships

Purpose, frequency, trigger, timing, interruptibility, and gesture rules shape the implementation.

Purpose

Preserve layout during loading and communicate ongoing work through a low-contrast shimmer.

Frequency

Show only when expected waiting exceeds a brief threshold, rendering fast results directly.

Trigger

Trigger after a loading-delay threshold and stop as soon as real content is ready.

Enter / exit

Show static placeholders first, loop a slow shimmer, and crossfade briefly into real content.

Interruptibility

Update state on cancel or retry without stacking shimmer timers.

Gesture and keyboard

Skeletons are noninteractive while cancel, back, or retry controls remain available.

Reduced-motion strategy

Disable shimmer and keep a static skeleton with explicit loading text.

Output

Copy into your interface

Current parameters update visual-state CSS, semantic HTML, the required vanilla JS runtime, and an interaction prompt.

Updates with parameters
motion.css
.motion-demo.motion-demo--skeleton-shimmer {
  position: relative;
  display: grid;
  place-items: center;
  width: min(100%, 34rem);
  min-height: 15rem;
  padding: 2rem;
  overflow: hidden;
  color: #18181b;
  background: #fafafa;
  border: 1px solid #e4e4e7;
  border-radius: 12px;
  isolation: isolate;
}

.motion-demo.motion-demo--skeleton-shimmer *, .motion-demo.motion-demo--skeleton-shimmer *::before, .motion-demo.motion-demo--skeleton-shimmer *::after {
  box-sizing: border-box;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-surface {
  position: relative;
  display: grid;
  gap: 0.65rem;
  width: min(100%, 18rem);
  padding: 1.25rem;
  background: #ffffff;
  border: 1px solid #e4e4e7;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 6%), 0 10px 28px rgb(0 0 0 / 7%);
}

.motion-demo.motion-demo--skeleton-shimmer .motion-line {
  display: block;
  width: 100%;
  height: 0.5rem;
  background: #e4e4e7;
  border-radius: 999px;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-line:last-child { width: 62%; }

.motion-demo.motion-demo--skeleton-shimmer .motion-button {
  position: relative;
  min-height: 2.75rem;
  padding: 0.75rem 1.1rem;
  color: white;
  font: inherit;
  font-weight: 700;
  background: #18181b;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }

.motion-demo.motion-demo--skeleton-shimmer .motion-action-row {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.85rem;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-replay-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-pausable-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--skeleton-shimmer button.motion-surface {
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-replay-button,
.motion-demo.motion-demo--skeleton-shimmer .motion-undo-button,
.motion-demo.motion-demo--skeleton-shimmer .motion-dismiss-button,
.motion-demo.motion-demo--skeleton-shimmer .motion-pause-button {
  min-height: 2.75rem;
  padding: 0.65rem 0.9rem;
  color: #18181b;
  font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
  background: #ffffff;
  border: 1px solid #d4d4d8;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-replay-button:focus-visible,
.motion-demo.motion-demo--skeleton-shimmer .motion-undo-button:focus-visible,
.motion-demo.motion-demo--skeleton-shimmer .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--skeleton-shimmer .motion-pause-button:focus-visible,
.motion-demo.motion-demo--skeleton-shimmer [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--skeleton-shimmer [data-swipe-target]:focus-visible {
  outline: 3px solid rgb(37 99 235 / 32%);
  outline-offset: 3px;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-ripple-ink {
  position: absolute;
  width: 12px;
  height: 12px;
  pointer-events: none;
  background: rgb(255 255 255 / 72%);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0.95);
  opacity: 0;
}

.motion-demo.motion-demo--skeleton-shimmer .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--skeleton-shimmer .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 8px; }
.motion-demo.motion-demo--skeleton-shimmer .motion-state--to { background: #18181b; color: white; }

.motion-demo.motion-demo--skeleton-shimmer .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--skeleton-shimmer .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--skeleton-shimmer .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--skeleton-shimmer svg { width: min(100%, 20rem); height: auto; }

.motion-demo.motion-demo--skeleton-shimmer .motion-skeleton { display: grid; gap: 0.7rem; width: min(100%, 18rem); }
.motion-demo.motion-demo--skeleton-shimmer .motion-skeleton-line { height: 0.8rem; overflow: hidden; background: #e4e4e7; border-radius: 999px; }
.motion-demo.motion-demo--skeleton-shimmer .motion-skeleton-line::after { content: ""; display: block; width: 45%; height: 100%; background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.14), transparent); animation: motion-skeleton-shimmer 1400ms linear infinite; }
@keyframes motion-skeleton-shimmer { from { transform: translateX(-120%); } to { transform: translateX(280%); } }

@keyframes motion-skeleton-shimmer-reduced-fade {
  from { opacity: 0.84; }
  to { opacity: 1; }
}

.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer {
  animation: motion-skeleton-shimmer-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}

.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer *,
.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer *::before,
.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer *::after {
  animation: none !important;
  animation-delay: 0ms !important;
  animation-iteration-count: 1 !important;
  transition-property: opacity, color, background-color, border-color !important;
  transition-duration: 160ms !important;
  transition-delay: 0ms !important;
  scroll-behavior: auto !important;
}

.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer .motion-button,
.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer [data-spring-target] {
  transform: none !important;
}

.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--skeleton-shimmer .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
  .motion-demo.motion-demo--skeleton-shimmer {
    animation: motion-skeleton-shimmer-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
  }

  .motion-demo.motion-demo--skeleton-shimmer *, .motion-demo.motion-demo--skeleton-shimmer *::before, .motion-demo.motion-demo--skeleton-shimmer *::after {
    animation: none !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity, color, background-color, border-color !important;
    transition-duration: 160ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .motion-demo.motion-demo--skeleton-shimmer .motion-button,
  .motion-demo.motion-demo--skeleton-shimmer [data-reorder-item],
  .motion-demo.motion-demo--skeleton-shimmer [data-swipe-target],
  .motion-demo.motion-demo--skeleton-shimmer [data-spring-target] {
    transform: none !important;
  }

  .motion-demo.motion-demo--skeleton-shimmer .motion-path { stroke-dashoffset: 0 !important; }
  .motion-demo.motion-demo--skeleton-shimmer .motion-word--from { opacity: 0 !important; visibility: hidden; }
  .motion-demo.motion-demo--skeleton-shimmer .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}
Review notes

Pre-delivery review

  • Match skeleton dimensions to real content to prevent completion shifts.
  • Pause shimmer when hidden or offscreen.
Accessibility

Keep information accessible

Reduced motion

Disable shimmer and keep a static skeleton with explicit loading text.

Parameters

Parameter reference

ParameterRange / optionsDefaultPurpose
duration800ms–3000ms1400msControls the rhythm of one full cycle; continuous motion should stay pausable and low-distraction.
intensity5%–30%14%Adjusts shimmer intensity.