loopLoop
循环An animation that repeats, a set number of times or infinitely.
按指定次数或无限重复播放的动画。
Compare loop direction, count, pauses, and rhythm while controlling distraction.
An animation that repeats, a set number of times or infinitely.
English definitions are preserved verbatim from Animation Vocabulary; translations and distinctions help you choose precisely.
loopAn animation that repeats, a set number of times or infinitely.
按指定次数或无限重复播放的动画。
alternateA loop that plays forward then reverses each iteration, instead of jumping back to the start.
每轮先正向播放再反向播放的循环,避免直接跳回起点。
Alternate reverses direction each iteration; Loop also includes normal, reverse, finite, and infinite strategies.
Purpose, frequency, trigger, timing, interruptibility, and gesture rules shape the implementation.
Control repeat direction, count, and pauses so loops communicate activity or waiting with limited distraction.
Run only while the underlying state persists and avoid permanent loops in ordinary content.
Trigger from loading, live, demo, or explicit play state, pausing when offscreen.
Pause on a stable frame between iterations and settle promptly when the state ends.
Resume from current progress after pause and cancel old loops with timer cleanup on state changes.
Allow hover, focus, and user controls to pause, with keyboard and assistive-technology support.
Stop automatic looping and show a representative static frame with explicit status text.
Current parameters update visual-state CSS, semantic HTML, the required vanilla JS runtime, and an interaction prompt.
.motion-demo.motion-demo--loop {
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--loop *, .motion-demo.motion-demo--loop *::before, .motion-demo.motion-demo--loop *::after {
box-sizing: border-box;
}
.motion-demo.motion-demo--loop .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--loop .motion-line {
display: block;
width: 100%;
height: 0.5rem;
background: #e4e4e7;
border-radius: 999px;
}
.motion-demo.motion-demo--loop .motion-line:last-child { width: 62%; }
.motion-demo.motion-demo--loop .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--loop .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }
.motion-demo.motion-demo--loop .motion-action-row {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-top: 0.85rem;
}
.motion-demo.motion-demo--loop .motion-replay-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--loop .motion-pausable-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--loop button.motion-surface {
color: inherit;
font: inherit;
text-align: start;
cursor: pointer;
}
.motion-demo.motion-demo--loop .motion-replay-button,
.motion-demo.motion-demo--loop .motion-undo-button,
.motion-demo.motion-demo--loop .motion-dismiss-button,
.motion-demo.motion-demo--loop .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--loop .motion-replay-button:focus-visible,
.motion-demo.motion-demo--loop .motion-undo-button:focus-visible,
.motion-demo.motion-demo--loop .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--loop .motion-pause-button:focus-visible,
.motion-demo.motion-demo--loop [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--loop [data-swipe-target]:focus-visible {
outline: 3px solid rgb(37 99 235 / 32%);
outline-offset: 3px;
}
.motion-demo.motion-demo--loop .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--loop .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--loop .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--loop .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--loop .motion-state--to { background: #18181b; color: white; }
.motion-demo.motion-demo--loop .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--loop .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--loop .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--loop svg { width: min(100%, 20rem); height: auto; }
.motion-demo.motion-demo--loop .motion-orbit-item { animation: motion-loop 1360ms cubic-bezier(0.77, 0, 0.175, 1) 0ms 3 normal; }
@keyframes motion-loop { 0%, 18% { transform: translateX(-54px); } 82%, 100% { transform: translateX(54px); } }
@keyframes motion-loop-reduced-fade {
from { opacity: 0.84; }
to { opacity: 1; }
}
.force-reduced-motion .motion-demo.motion-demo--loop {
animation: motion-loop-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.force-reduced-motion .motion-demo.motion-demo--loop *,
.force-reduced-motion .motion-demo.motion-demo--loop *::before,
.force-reduced-motion .motion-demo.motion-demo--loop *::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--loop .motion-button,
.force-reduced-motion .motion-demo.motion-demo--loop [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--loop [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--loop [data-spring-target] {
transform: none !important;
}
.force-reduced-motion .motion-demo.motion-demo--loop .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--loop .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--loop .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
@media (prefers-reduced-motion: reduce) {
.motion-demo.motion-demo--loop {
animation: motion-loop-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.motion-demo.motion-demo--loop *, .motion-demo.motion-demo--loop *::before, .motion-demo.motion-demo--loop *::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--loop .motion-button,
.motion-demo.motion-demo--loop [data-reorder-item],
.motion-demo.motion-demo--loop [data-swipe-target],
.motion-demo.motion-demo--loop [data-spring-target] {
transform: none !important;
}
.motion-demo.motion-demo--loop .motion-path { stroke-dashoffset: 0 !important; }
.motion-demo.motion-demo--loop .motion-word--from { opacity: 0 !important; visibility: hidden; }
.motion-demo.motion-demo--loop .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}Stop automatic looping and show a representative static frame with explicit status text.
| Parameter | Range / options | Default | Purpose |
|---|---|---|---|
duration | 800ms–4000ms | 1200ms | Controls the rhythm of one full cycle; continuous motion should stay pausable and low-distraction. |
pause | 0ms–800ms | 160ms | Adjusts loop pause. |
direction | Normal / Alternate / Reverse | Normal | Selects loop direction. |
iterations | 1x–8x | 3x | Adjusts iterations. |
infinite | On / Off | Off | Keeps the motion looping. |