← Back to gallery
CSS

Idle Wiggle Feedback Loop

A restrained feedback loop that uses a short low-amplitude wiggle burst and a long rest phase so empty or waiting states feel alive without constant motion.

idle-animationwigglefeedbacktransform-originlow-amplitudeempty-stateprefers-reduced-motion

Feedback / idle loop / restrained motion

Idle Wiggle Feedback Loop

Three low-amplitude idle feedback loops use short wiggle bursts and long rests so empty or waiting states stay alive without nagging the user.

Short burst · long rest

Rotate Burst

Low-amplitude wiggle with a long calm segment.

  • idle
  • rotate
  • rest

TranslateY · calm feedback

Y-axis Bob

A restrained y-axis bob with the same long-rest timing.

  • translateY
  • y-axis
  • calm

Secondary cue · no layout

Secondary Pulse

Shift emphasis to a small secondary cue when motion must be subtle.

  • pulse
  • secondary cue
  • low motion

Idle wiggle inspector

Rotate Burst

  • idle
  • rotate
  • rest

A tiny rotate burst fires once per cycle and spends most of the loop at rest, avoiding constant motion.

Helped you ship something? 🐟 Send my cat a churu

/* Rotate Burst: Low-amplitude wiggle with a long calm segment. */
.motion-idle-rotate-burst__target {
  --motion-duration: 4.8s;
  display: inline-grid;
  place-items: center;
  min-width: 7rem;
  min-height: 3rem;
  border-radius: .9rem;
  background: #67e8f9;
  transform-origin: 50% 82%;
  animation: idle-rotate-burst var(--motion-duration) ease-in-out infinite;
}

@keyframes idle-rotate-burst {
  0%, 70%, 100% { transform: rotate(0deg); }
  76% { transform: rotate(calc(-4deg * 1.00)); }
  82% { transform: rotate(calc(3deg * 1.00)); }
  88% { transform: rotate(0deg); }
}

@media (prefers-reduced-motion: reduce) {
  .motion-idle-rotate-burst__target { animation: none; }
}

How to make this

An idle wiggle feedback loop holds still for most of its keyframe, then runs a short low-amplitude transform burst around a tuned origin.

html
<button class="idle-nudge" type="button">  Review empty state</button> <style>.idle-nudge {7  transform-origin: 50% 80%;  border: 0;  border-radius: 999px;  padding: .8rem 1.1rem;  color: #0f172a;  background: #fbbf24;  font-weight: 700;14  animation: idle-wiggle 5s ease-in-out infinite;}@keyframes idle-wiggle {17  0%, 68%, 100% { transform: rotate(0deg) translateY(0); }18  72% { transform: rotate(-3deg) translateY(-1px); }  76% { transform: rotate(3deg) translateY(-1px); }  80% { transform: rotate(-1.5deg) translateY(0); }  84% { transform: rotate(0deg) translateY(0); }}23@media (prefers-reduced-motion: reduce) {  .idle-nudge { animation: none; }}</style>

Annotated snippet

  1. Line 7The origin decides whether the wiggle feels like a natural nudge or a random shake.
    PitfallHow should I choose transform-origin for a wiggle?

    Put the origin near the visual anchor. Bottom-heavy objects often feel better with an origin near the lower center.

  2. Line 14The loop belongs on the single nudge target. Avoid applying idle motion to whole sections.

    The UI is identical. Moving the whole card feels noisy, while scoping motion to the action cue keeps the same layout calmer.

    PitfallCan an entire empty state wiggle?

    Avoid moving whole sections. Wiggle a small icon or button so nearby reading content stays still.

  3. Line 17The long hold is the point: most of the cycle is rest, not movement.

    The UI is identical. Constant rotation keeps moving, while the rest-burst keyframe holds still before the same card briefly rotates.

    PitfallHow much of the loop should be still?

    Most of it. A burst after a long hold is attention feedback; constant movement is ambient noise.

  4. Line 18Amplitude stays small. Larger values start to look like error shake feedback.
    PitfallHow large should the wiggle be?

    Small, usually 1 to 4 degrees. Larger motion reads as an error shake or a playful character animation.

  5. Line 23Reduced motion removes the wiggle but leaves the call to action visible.
    PitfallShould reduced motion use a slower wiggle?

    No. Stop the wiggle and preserve the visible message or button.

Other pitfalls

What should I verify before shipping this pattern?
Check that the preview card and showcase communicate the same start and end state, every inspector control visibly changes the animation, compare demos stay fixed-height and centered, and reduced motion preserves the information without running a substitute loop.

Notes

Overview

Idle wiggle is a timing pattern, not a mascot or empty-state domain. A short transform burst is followed by a long rest so the object asks for attention without constant motion. The rest period is as important as the wiggle itself: without it, the pattern becomes noise instead of a soft nudge.

When to use it

Use it for non-critical reminders, empty states, onboarding affordances, retry hints, and small affordances that may otherwise be missed. It is strongest when the user is idle or scanning, not actively typing or reading. Avoid it near text input, reading flows, high-frequency dashboards, or anything that might be mistaken for an error shake.

How it works

A single keyframe holds the neutral state for most of its duration, then runs a small rotate or translate burst around a tuned transform-origin. The transform origin should match the object: a hanging tag pivots from the top, a card might lift from center, and a small icon can use a scale pulse.

Production gotchas

Low amplitude matters. Large wiggles feel like errors or shake feedback, and constant loops become irritating quickly. Keep controls in the inspector tied to amplitude, rest length, and origin only if they visibly affect the loop; otherwise the UI implies configurability that the animation does not actually have.

Accessibility

The wiggle is decorative feedback. The same message or action needs visible text, a reachable control, or a clear state outside the motion. Reduced motion should freeze the object while preserving any call to action, and the loop should stop once the user has acted or dismissed the nudge.

References

Implementation depth

Idle wiggle is a feedback timing pattern: a short low-amplitude burst followed by a long quiet rest. The useful mechanic is the duty cycle, not the object being wiggled, so the same expression can support empty states, reminders, and soft nudges.

Do not run constant attention motion near primary reading or form entry. Keep the transform origin natural, make the wiggle opt-in for non-critical surfaces, and freeze the object under reduced motion while keeping any message or call to action visible.

A good wiggle spends more time resting than moving. If the loop is always active, users learn to ignore it or read it as an error state; the delay ratio is part of the design, not just timing polish.

Tie the motion to lifecycle. Stop the wiggle after the user interacts, dismisses the nudge, or resolves the empty state so the animation does not keep asking for attention after it has served its purpose.