Idle animation
Use subtle breathing or floating motion for available, waiting, or active states.
Live preview
Subtle motion that plays while an element is just sitting there, waiting to be interacted with.
Definition and close-term distinctions
English definitions are preserved verbatim from Animation Vocabulary; translations and distinctions help you choose precisely.
idle-animationIdle animation
空闲动效Subtle motion that plays while an element is just sitting there, waiting to be interacted with.
元素静置并等待交互时播放的细微运动。
pulsePulse
脉冲A gentle repeating scale or opacity change to draw attention.
通过轻柔重复的缩放或透明度变化吸引注意。
Pulse repeats scale or opacity changes to attract attention; Idle animation is the broader category that can include it.
floatFloat
漂浮A gentle, continuous up-and-down drift that makes a static element feel alive and weightless.
轻柔、持续的上下漂移,让静态元素显得有生命力且轻盈。
Float uses continuous subtle vertical drift; Idle animation can also use pulse and other low-intensity motion.
Decide before this motion ships
Purpose, frequency, trigger, timing, interruptibility, and gesture rules shape the implementation.
Use low-amplitude float or pulse motion to indicate availability, waiting, or activity.
Appear only after a meaningful idle period and stop immediately when the user interacts.
Trigger from an idle timer or ongoing state, pausing when hidden or offscreen.
Ease into a low-amplitude loop and stop on the nearest neutral frame.
Cancel on input and settle to a stable value without overlapping interaction feedback.
Idle motion carries no action; real controls keep explicit click, touch, and keyboard feedback.
Disable automatic float and pulse motion and use a static status indicator.
Copy into your interface
Current parameters update visual-state CSS, semantic HTML, the required vanilla JS runtime, and an interaction prompt.
.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; }
}Pre-delivery review
- Start only after the interface is genuinely idle.
- Limit amplitude and contrast to avoid persistent attention capture.
Keep information accessible
Disable automatic float and pulse motion and use a static status indicator.
Parameter reference
| Parameter | Range / options | Default | Purpose |
|---|---|---|---|
duration | 1000ms–6000ms | 2200ms | Controls the rhythm of one full cycle; continuous motion should stay pausable and low-distraction. |
distance | 0px–24px | 8px | Controls how far the element travels. |
style | Float / Pulse | Float | Selects idle style. |
pause | 0ms–1200ms | 300ms | Adjusts pause. |