Skip to content
WebTricks

Shake animation

A horizontal shake built with @keyframes — great for signalling an invalid input or a wrong action.

  • animation
  • keyframes
  • shake
  • error
  • feedback
Distance6px
Duration500ms
HTML
<button class="shake">Hover to shake</button>
CSS
:root {
    --dist: 6px;
    --speed: 500ms;
}

.shake {
    padding: 10px 18px;
    border: 1px solid #e5484d;
    border-radius: 8px;
    background: #1b1f2a;
    color: #fff;
    cursor: pointer;
}

/* Trigger on hover for the demo; in an app, add a .is-invalid class instead */
.shake:hover {
    animation: shake var(--speed) ease;
}

@keyframes shake {
    10%, 90% { transform: translateX(calc(var(--dist) * -1)); }
    20%, 80% { transform: translateX(var(--dist)); }
    30%, 50%, 70% { transform: translateX(calc(var(--dist) * -1)); }
    40%, 60% { transform: translateX(var(--dist)); }
}

@media (prefers-reduced-motion: reduce) {
    .shake:hover { animation: none; }
}

How it works

@keyframes defines the steps of a named animation; the animation property plays it. Here the element jumps left and right at decreasing intervals to read as a “shake”.

  • The keyframe percentages cluster the movement so it’s a quick burst, settling back to centre at 0%/100%.
  • It animates transform: translateX, which is GPU-friendly and won’t shift surrounding layout.
  • In a real form, toggle a class like .is-invalid (in JS, on a failed submit) instead of :hover, then remove it after the animation ends.
  • The prefers-reduced-motion block respects users who opt out of motion.

For a looping example instead of a one-shot, see the transitions and animations guide.