Idle animation

Use subtle breathing or floating motion for available, waiting, or active states.

Preview

Live preview

Subtle motion that plays while an element is just sitting there, waiting to be interacted with.

Preview
Idle animation
Authoritative vocabulary

Definition and close-term distinctions

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

Canonical termidle-animation

Idle animation

空闲动效
Authoritative definition

Subtle motion that plays while an element is just sitting there, waiting to be interacted with.

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

Use low-amplitude float or pulse motion to indicate availability, waiting, or activity.

Frequency

Appear only after a meaningful idle period and stop immediately when the user interacts.

Trigger

Trigger from an idle timer or ongoing state, pausing when hidden or offscreen.

Enter / exit

Ease into a low-amplitude loop and stop on the nearest neutral frame.

Interruptibility

Cancel on input and settle to a stable value without overlapping interaction feedback.

Gesture and keyboard

Idle motion carries no action; real controls keep explicit click, touch, and keyboard feedback.

Reduced-motion strategy

Disable automatic float and pulse motion and use a static status indicator.

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--idle-animation {
  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--idle-animation *, .motion-demo.motion-demo--idle-animation *::before, .motion-demo.motion-demo--idle-animation *::after {
  box-sizing: border-box;
}

.motion-demo.motion-demo--idle-animation .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--idle-animation .motion-line {
  display: block;
  width: 100%;
  height: 0.5rem;
  background: #e4e4e7;
  border-radius: 999px;
}

.motion-demo.motion-demo--idle-animation .motion-line:last-child { width: 62%; }

.motion-demo.motion-demo--idle-animation .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--idle-animation .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }

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

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

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

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

.motion-demo.motion-demo--idle-animation .motion-replay-button,
.motion-demo.motion-demo--idle-animation .motion-undo-button,
.motion-demo.motion-demo--idle-animation .motion-dismiss-button,
.motion-demo.motion-demo--idle-animation .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--idle-animation .motion-replay-button:focus-visible,
.motion-demo.motion-demo--idle-animation .motion-undo-button:focus-visible,
.motion-demo.motion-demo--idle-animation .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--idle-animation .motion-pause-button:focus-visible,
.motion-demo.motion-demo--idle-animation [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--idle-animation [data-swipe-target]:focus-visible {
  outline: 3px solid rgb(37 99 235 / 32%);
  outline-offset: 3px;
}

.motion-demo.motion-demo--idle-animation .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--idle-animation .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--idle-animation .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--idle-animation .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--idle-animation .motion-state--to { background: #18181b; color: white; }

.motion-demo.motion-demo--idle-animation .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--idle-animation .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--idle-animation .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--idle-animation svg { width: min(100%, 20rem); height: auto; }

.motion-demo.motion-demo--idle-animation .motion-surface { animation: motion-idle-animation 2500ms cubic-bezier(0.77, 0, 0.175, 1) infinite; }
@keyframes motion-idle-animation { 0%, 100% { opacity: 1; transform: none; } 50% { transform: translateY(-8px); } }

@keyframes motion-idle-animation-reduced-fade {
  from { opacity: 0.84; }
  to { opacity: 1; }
}

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

.force-reduced-motion .motion-demo.motion-demo--idle-animation *,
.force-reduced-motion .motion-demo.motion-demo--idle-animation *::before,
.force-reduced-motion .motion-demo.motion-demo--idle-animation *::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--idle-animation .motion-button,
.force-reduced-motion .motion-demo.motion-demo--idle-animation [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--idle-animation [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--idle-animation [data-spring-target] {
  transform: none !important;
}

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

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

  .motion-demo.motion-demo--idle-animation *, .motion-demo.motion-demo--idle-animation *::before, .motion-demo.motion-demo--idle-animation *::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--idle-animation .motion-button,
  .motion-demo.motion-demo--idle-animation [data-reorder-item],
  .motion-demo.motion-demo--idle-animation [data-swipe-target],
  .motion-demo.motion-demo--idle-animation [data-spring-target] {
    transform: none !important;
  }

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

Pre-delivery review

  • Start only after the interface is genuinely idle.
  • Limit amplitude and contrast to avoid persistent attention capture.
Accessibility

Keep information accessible

Reduced motion

Disable automatic float and pulse motion and use a static status indicator.

Parameters

Parameter reference

ParameterRange / optionsDefaultPurpose
duration1000ms–6000ms2200msControls the rhythm of one full cycle; continuous motion should stay pausable and low-distraction.
distance0px–24px8pxControls how far the element travels.
styleFloat / PulseFloatSelects idle style.
pause0ms–1200ms300msAdjusts pause.