Shake / Wiggle

Use one brief horizontal shake for errors or inputs that need attention.

Preview

Live preview

A quick side-to-side jitter signaling an error or rejected input.

Preview
Shake / Wiggle
Authoritative vocabulary

Definition and close-term distinctions

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

Canonical termshake-wiggle

Shake / Wiggle

摇晃 / 抖动
Authoritative definition

A quick side-to-side jitter signaling an error or rejected input.

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 one brief horizontal motion to signal an error, rejection, or input needing attention.

Frequency

Use infrequently for explicit errors and avoid repetition during continuous validation.

Trigger

Trigger on submission failure or server rejection while showing readable error text.

Enter / exit

Run 2–3 decaying oscillations when the error appears, with no reverse animation when cleared.

Interruptibility

Stop shaking on new input and retrigger only after another submission.

Gesture and keyboard

No gesture is required; move focus to an error summary or first invalid field with a clear keyboard path.

Reduced-motion strategy

Remove travel and use error border, icon, and text, with at most one brief color pulse.

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

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

.motion-demo.motion-demo--shake-wiggle .motion-line:last-child { width: 62%; }

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

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

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

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

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

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

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

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

.motion-demo.motion-demo--shake-wiggle .motion-surface { animation: motion-shake-wiggle 240ms cubic-bezier(0.77, 0, 0.175, 1) both; border-color: #b34d37; }
@keyframes motion-shake-wiggle { 0%, 100% { transform: none; } 14% { transform: translateX(10px); } 29% { transform: translateX(-9px); } 43% { transform: translateX(7px); } 57% { transform: translateX(-6px); } 71% { transform: translateX(4px); } 86% { transform: translateX(-3px); } }

@keyframes motion-shake-wiggle-reduced-fade {
  from { opacity: 0.84; }
  to { opacity: 1; }
}

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

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

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

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

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

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

Pre-delivery review

  • Never rely on shaking in place of error copy.
  • Keep amplitude small and avoid moving a page or large container.
Accessibility

Keep information accessible

Reduced motion

Remove travel and use error border, icon, and text, with at most one brief color pulse.

Parameters

Parameter reference

ParameterRange / optionsDefaultPurpose
duration80ms–1200ms240msControls the time required for one motion cycle.
distance0px–30px10pxControls how far the element travels.
cycles1–63Adjusts cycles.