30 CSS Shake Animations23 / 30
CSS Vertical Shake Animation
The vertical axis has different physics: a jackhammer specimen that hammers downward with asymmetric frames (fast down, slow up — impacts are one-sided), and a landing thud where a dropped card hits, compresses, and rings out a decaying vertical shudder with a dust-line flash.
Published
The code
<div class="shk-23-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@600..900&family=IBM+Plex+Mono:wght@500;600&display=swap" rel="stylesheet">
<section class="shk-23a" aria-label="Jackhammer vertical shake specimen">
<div class="shk-23a__site">
<p class="shk-23a__permit">PERMIT NO. 23-Y · VERTICAL WORKS</p>
<div class="shk-23a__stage">
<div class="shk-23a__hammer" tabindex="0" aria-label="Hammering block — hover to pause">UNDER<br>CONSTRUCTION</div>
<div class="shk-23a__ground" aria-hidden="true"></div>
</div>
<p class="shk-23a__note">down-strokes 6px & fast · up-strokes 1px & lazy — impacts are one-sided</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400..700&display=swap" rel="stylesheet">
<section class="shk-23b" aria-label="Card that drops, thuds and shudders">
<div class="shk-23b__stage">
<div class="shk-23b__card" tabindex="0">
<p class="shk-23b__big">17,4 kg</p>
<p class="shk-23b__small">delivered · signature not required</p>
</div>
<div class="shk-23b__shadow" aria-hidden="true"></div>
<p class="shk-23b__hint" aria-hidden="true">replays every 3.5s (hover to pause) — drop → squash → decaying vertical shudder, one timeline</p>
</div>
</section>
</div><div class="shk-23-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@600..900&family=IBM+Plex+Mono:wght@500;600&display=swap" rel="stylesheet">
<section class="shk-23a" aria-label="Jackhammer vertical shake specimen">
<div class="shk-23a__site">
<p class="shk-23a__permit">PERMIT NO. 23-Y · VERTICAL WORKS</p>
<div class="shk-23a__stage">
<div class="shk-23a__hammer" tabindex="0" aria-label="Hammering block — hover to pause">UNDER<br>CONSTRUCTION</div>
<div class="shk-23a__ground" aria-hidden="true"></div>
</div>
<p class="shk-23a__note">down-strokes 6px & fast · up-strokes 1px & lazy — impacts are one-sided</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400..700&display=swap" rel="stylesheet">
<section class="shk-23b" aria-label="Card that drops, thuds and shudders">
<div class="shk-23b__stage">
<div class="shk-23b__card" tabindex="0">
<p class="shk-23b__big">17,4 kg</p>
<p class="shk-23b__small">delivered · signature not required</p>
</div>
<div class="shk-23b__shadow" aria-hidden="true"></div>
<p class="shk-23b__hint" aria-hidden="true">replays every 3.5s (hover to pause) — drop → squash → decaying vertical shudder, one timeline</p>
</div>
</section>
</div>.shk-23-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.shk-23-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.shk-23a,
.shk-23a *,
.shk-23a *::before,
.shk-23a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23a {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: repeating-linear-gradient(45deg,#f4c81d 0 26px,#191713 26px 52px);
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.shk-23a__site {
width: min(440px,100%);
padding: 30px 32px 26px;
background: #f7f4ea;
border: 3px solid #191713;
border-radius: 6px;
box-shadow: 10px 10px 0 rgba(25,23,19,.85);
}
.shk-23a__permit {
font-family: 'IBM Plex Mono',ui-monospace,monospace;
font-size: 10.5px;
font-weight: 600;
letter-spacing: .14em;
color: #191713;
border-bottom: 2px dashed rgba(25,23,19,.3);
padding-bottom: 10px;
}
.shk-23a__stage {
margin-top: 26px;
display: grid;
justify-items: center;
}
.shk-23a__hammer {
padding: 22px 30px;
text-align: center;
font-size: 21px;
line-height: 1.15;
font-weight: 900;
letter-spacing: .04em;
color: #f7f4ea;
background: #191713;
border-radius: 4px;
transform-origin: 50% 100%;
animation: shk-23a-hammer .5s linear infinite;
outline: none;
}
.shk-23a__hammer:hover,
.shk-23a__hammer:focus-visible {
animation-play-state: paused;
}
.shk-23a__ground {
width: 78%;
height: 5px;
margin-top: 6px;
background: rgba(25,23,19,.85);
border-radius: 999px;
animation: shk-23a-dust .5s linear infinite;
}
.shk-23a__note {
margin-top: 22px;
font-size: 12px;
font-weight: 600;
color: rgba(25,23,19,.6);
text-align: center;
text-wrap: pretty;
}
@keyframes shk-23a-hammer {
0%,
100% {
translate: 0 0;
scale: 1 1;
}
15% {
translate: 0 6px;
scale: 1.05 .94;
}
35% {
translate: 0 -1px;
scale: 1 1;
}
50% {
translate: 0 5px;
scale: 1.04 .95;
}
70% {
translate: 0 -.5px;
scale: 1 1;
}
85% {
translate: 0 4px;
scale: 1.03 .96;
}
}
@keyframes shk-23a-dust {
0%,
100% {
scale: 1 1;
opacity: .85;
}
15% {
scale: 1.06 1;
opacity: 1;
}
50% {
scale: 1.05 1;
}
85% {
scale: 1.04 1;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23a__hammer,
.shk-23a__ground {
animation: none;
}
}
.shk-23b,
.shk-23b *,
.shk-23b *::before,
.shk-23b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23b {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 100% at 50% 0%,#1b1e26,#101218 65%);
font-family: 'Space Grotesk','Segoe UI',system-ui,sans-serif;
}
.shk-23b__stage {
display: grid;
justify-items: center;
}
.shk-23b__card {
padding: 30px 44px;
text-align: center;
background: linear-gradient(180deg,#f2e8d8,#e2d2b8);
border-radius: 14px;
box-shadow: 0 24px 45px -20px rgba(0,0,0,.75);
transform-origin: 50% 100%;
animation: shk-23b-thud 3.5s cubic-bezier(.5,0,.7,.3) infinite;
outline: none;
}
.shk-23b__card:hover,
.shk-23b__card:focus-visible {
animation-play-state: paused;
}
.shk-23b__big {
font-size: 34px;
font-weight: 700;
letter-spacing: -.02em;
color: #2c2416;
}
.shk-23b__small {
margin-top: 6px;
font-size: 12.5px;
color: rgba(44,36,22,.55);
}
.shk-23b__shadow {
width: 200px;
height: 12px;
margin-top: 14px;
border-radius: 50%;
background: rgba(0,0,0,.55);
filter: blur(5px);
animation: shk-23b-shadow 3.5s cubic-bezier(.5,0,.7,.3) infinite;
}
.shk-23b__hint {
margin-top: 26px;
font-size: 12px;
color: rgba(230,235,248,.4);
max-width: 420px;
text-align: center;
}
@keyframes shk-23b-thud {
0% {
translate: 0 -120px;
scale: 1 1;
opacity: 0;
}
6% {
opacity: 1;
}
12% {
translate: 0 0;
scale: 1 1;
}
15% {
scale: 1.12 .84;
}
20% {
scale: .96 1.05;
}
25% {
translate: 0 3px;
scale: 1.03 .97;
}
31% {
translate: 0 -1.5px;
scale: 1 1;
}
37% {
translate: 0 1.5px;
}
43% {
translate: 0 -.5px;
}
48%,
86% {
translate: 0 0;
scale: 1 1;
}
100% {
translate: 0 -120px;
opacity: 0;
}
}
@keyframes shk-23b-shadow {
0% {
scale: .45 1;
opacity: .25;
}
12% {
scale: 1 1;
opacity: .8;
}
15% {
scale: 1.15 1;
}
25% {
scale: 1.04 1;
}
48%,
86% {
scale: 1 1;
opacity: .8;
}
100% {
scale: .45 1;
opacity: .25;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23b__card,
.shk-23b__shadow {
animation: none;
}
}.shk-23-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.shk-23-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.shk-23a,
.shk-23a *,
.shk-23a *::before,
.shk-23a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23a {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: repeating-linear-gradient(45deg,#f4c81d 0 26px,#191713 26px 52px);
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.shk-23a__site {
width: min(440px,100%);
padding: 30px 32px 26px;
background: #f7f4ea;
border: 3px solid #191713;
border-radius: 6px;
box-shadow: 10px 10px 0 rgba(25,23,19,.85);
}
.shk-23a__permit {
font-family: 'IBM Plex Mono',ui-monospace,monospace;
font-size: 10.5px;
font-weight: 600;
letter-spacing: .14em;
color: #191713;
border-bottom: 2px dashed rgba(25,23,19,.3);
padding-bottom: 10px;
}
.shk-23a__stage {
margin-top: 26px;
display: grid;
justify-items: center;
}
.shk-23a__hammer {
padding: 22px 30px;
text-align: center;
font-size: 21px;
line-height: 1.15;
font-weight: 900;
letter-spacing: .04em;
color: #f7f4ea;
background: #191713;
border-radius: 4px;
transform-origin: 50% 100%;
animation: shk-23a-hammer .5s linear infinite;
outline: none;
}
.shk-23a__hammer:hover,
.shk-23a__hammer:focus-visible {
animation-play-state: paused;
}
.shk-23a__ground {
width: 78%;
height: 5px;
margin-top: 6px;
background: rgba(25,23,19,.85);
border-radius: 999px;
animation: shk-23a-dust .5s linear infinite;
}
.shk-23a__note {
margin-top: 22px;
font-size: 12px;
font-weight: 600;
color: rgba(25,23,19,.6);
text-align: center;
text-wrap: pretty;
}
@keyframes shk-23a-hammer {
0%,
100% {
translate: 0 0;
scale: 1 1;
}
15% {
translate: 0 6px;
scale: 1.05 .94;
}
35% {
translate: 0 -1px;
scale: 1 1;
}
50% {
translate: 0 5px;
scale: 1.04 .95;
}
70% {
translate: 0 -.5px;
scale: 1 1;
}
85% {
translate: 0 4px;
scale: 1.03 .96;
}
}
@keyframes shk-23a-dust {
0%,
100% {
scale: 1 1;
opacity: .85;
}
15% {
scale: 1.06 1;
opacity: 1;
}
50% {
scale: 1.05 1;
}
85% {
scale: 1.04 1;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23a__hammer,
.shk-23a__ground {
animation: none;
}
}
.shk-23b,
.shk-23b *,
.shk-23b *::before,
.shk-23b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23b {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 100% at 50% 0%,#1b1e26,#101218 65%);
font-family: 'Space Grotesk','Segoe UI',system-ui,sans-serif;
}
.shk-23b__stage {
display: grid;
justify-items: center;
}
.shk-23b__card {
padding: 30px 44px;
text-align: center;
background: linear-gradient(180deg,#f2e8d8,#e2d2b8);
border-radius: 14px;
box-shadow: 0 24px 45px -20px rgba(0,0,0,.75);
transform-origin: 50% 100%;
animation: shk-23b-thud 3.5s cubic-bezier(.5,0,.7,.3) infinite;
outline: none;
}
.shk-23b__card:hover,
.shk-23b__card:focus-visible {
animation-play-state: paused;
}
.shk-23b__big {
font-size: 34px;
font-weight: 700;
letter-spacing: -.02em;
color: #2c2416;
}
.shk-23b__small {
margin-top: 6px;
font-size: 12.5px;
color: rgba(44,36,22,.55);
}
.shk-23b__shadow {
width: 200px;
height: 12px;
margin-top: 14px;
border-radius: 50%;
background: rgba(0,0,0,.55);
filter: blur(5px);
animation: shk-23b-shadow 3.5s cubic-bezier(.5,0,.7,.3) infinite;
}
.shk-23b__hint {
margin-top: 26px;
font-size: 12px;
color: rgba(230,235,248,.4);
max-width: 420px;
text-align: center;
}
@keyframes shk-23b-thud {
0% {
translate: 0 -120px;
scale: 1 1;
opacity: 0;
}
6% {
opacity: 1;
}
12% {
translate: 0 0;
scale: 1 1;
}
15% {
scale: 1.12 .84;
}
20% {
scale: .96 1.05;
}
25% {
translate: 0 3px;
scale: 1.03 .97;
}
31% {
translate: 0 -1.5px;
scale: 1 1;
}
37% {
translate: 0 1.5px;
}
43% {
translate: 0 -.5px;
}
48%,
86% {
translate: 0 0;
scale: 1 1;
}
100% {
translate: 0 -120px;
opacity: 0;
}
}
@keyframes shk-23b-shadow {
0% {
scale: .45 1;
opacity: .25;
}
12% {
scale: 1 1;
opacity: .8;
}
15% {
scale: 1.15 1;
}
25% {
scale: 1.04 1;
}
48%,
86% {
scale: 1 1;
opacity: .8;
}
100% {
scale: .45 1;
opacity: .25;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23b__card,
.shk-23b__shadow {
animation: none;
}
}/* No JavaScript — down-frames are large/fast, up-frames small/slow (gravity is asymmetric), each contact squashes via scale with transform-origin at the bottom edge, and the ground line stretches in sympathy on the same clock. */ /* No JavaScript — fall, squash, and shudder are segments of ONE keyframe timeline, with the ground shadow scaling on a matching clock so light and mass agree. Faking physics = choreographing consequences. */
/* No JavaScript — down-frames are large/fast, up-frames small/slow (gravity is asymmetric), each contact squashes via scale with transform-origin at the bottom edge, and the ground line stretches in sympathy on the same clock. */
/* No JavaScript — fall, squash, and shudder are segments of ONE keyframe timeline, with the ground shadow scaling on a matching clock so light and mass agree. Faking physics = choreographing consequences. */Here's a working CSS Shake Animation from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Vertical Shake Animation
Source: https://codefronts.com/motion/css-shake-animation/css-vertical-shake-animation/
The vertical axis has different physics: a jackhammer specimen that hammers downward with asymmetric frames (fast down, slow up — impacts are one-sided), and a landing thud where a dropped card hits, compresses, and rings out a decaying vertical shudder with a dust-line flash.
## HTML
```html
<div class="shk-23-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@600..900&family=IBM+Plex+Mono:wght@500;600&display=swap" rel="stylesheet">
<section class="shk-23a" aria-label="Jackhammer vertical shake specimen">
<div class="shk-23a__site">
<p class="shk-23a__permit">PERMIT NO. 23-Y · VERTICAL WORKS</p>
<div class="shk-23a__stage">
<div class="shk-23a__hammer" tabindex="0" aria-label="Hammering block — hover to pause">UNDER<br>CONSTRUCTION</div>
<div class="shk-23a__ground" aria-hidden="true"></div>
</div>
<p class="shk-23a__note">down-strokes 6px & fast · up-strokes 1px & lazy — impacts are one-sided</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400..700&display=swap" rel="stylesheet">
<section class="shk-23b" aria-label="Card that drops, thuds and shudders">
<div class="shk-23b__stage">
<div class="shk-23b__card" tabindex="0">
<p class="shk-23b__big">17,4 kg</p>
<p class="shk-23b__small">delivered · signature not required</p>
</div>
<div class="shk-23b__shadow" aria-hidden="true"></div>
<p class="shk-23b__hint" aria-hidden="true">replays every 3.5s (hover to pause) — drop → squash → decaying vertical shudder, one timeline</p>
</div>
</section>
</div>
```
## CSS
```css
.shk-23-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.shk-23-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.shk-23a,
.shk-23a *,
.shk-23a *::before,
.shk-23a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23a {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: repeating-linear-gradient(45deg,#f4c81d 0 26px,#191713 26px 52px);
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.shk-23a__site {
width: min(440px,100%);
padding: 30px 32px 26px;
background: #f7f4ea;
border: 3px solid #191713;
border-radius: 6px;
box-shadow: 10px 10px 0 rgba(25,23,19,.85);
}
.shk-23a__permit {
font-family: 'IBM Plex Mono',ui-monospace,monospace;
font-size: 10.5px;
font-weight: 600;
letter-spacing: .14em;
color: #191713;
border-bottom: 2px dashed rgba(25,23,19,.3);
padding-bottom: 10px;
}
.shk-23a__stage {
margin-top: 26px;
display: grid;
justify-items: center;
}
.shk-23a__hammer {
padding: 22px 30px;
text-align: center;
font-size: 21px;
line-height: 1.15;
font-weight: 900;
letter-spacing: .04em;
color: #f7f4ea;
background: #191713;
border-radius: 4px;
transform-origin: 50% 100%;
animation: shk-23a-hammer .5s linear infinite;
outline: none;
}
.shk-23a__hammer:hover,
.shk-23a__hammer:focus-visible {
animation-play-state: paused;
}
.shk-23a__ground {
width: 78%;
height: 5px;
margin-top: 6px;
background: rgba(25,23,19,.85);
border-radius: 999px;
animation: shk-23a-dust .5s linear infinite;
}
.shk-23a__note {
margin-top: 22px;
font-size: 12px;
font-weight: 600;
color: rgba(25,23,19,.6);
text-align: center;
text-wrap: pretty;
}
@keyframes shk-23a-hammer {
0%,
100% {
translate: 0 0;
scale: 1 1;
}
15% {
translate: 0 6px;
scale: 1.05 .94;
}
35% {
translate: 0 -1px;
scale: 1 1;
}
50% {
translate: 0 5px;
scale: 1.04 .95;
}
70% {
translate: 0 -.5px;
scale: 1 1;
}
85% {
translate: 0 4px;
scale: 1.03 .96;
}
}
@keyframes shk-23a-dust {
0%,
100% {
scale: 1 1;
opacity: .85;
}
15% {
scale: 1.06 1;
opacity: 1;
}
50% {
scale: 1.05 1;
}
85% {
scale: 1.04 1;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23a__hammer,
.shk-23a__ground {
animation: none;
}
}
.shk-23b,
.shk-23b *,
.shk-23b *::before,
.shk-23b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23b {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 100% at 50% 0%,#1b1e26,#101218 65%);
font-family: 'Space Grotesk','Segoe UI',system-ui,sans-serif;
}
.shk-23b__stage {
display: grid;
justify-items: center;
}
.shk-23b__card {
padding: 30px 44px;
text-align: center;
background: linear-gradient(180deg,#f2e8d8,#e2d2b8);
border-radius: 14px;
box-shadow: 0 24px 45px -20px rgba(0,0,0,.75);
transform-origin: 50% 100%;
animation: shk-23b-thud 3.5s cubic-bezier(.5,0,.7,.3) infinite;
outline: none;
}
.shk-23b__card:hover,
.shk-23b__card:focus-visible {
animation-play-state: paused;
}
.shk-23b__big {
font-size: 34px;
font-weight: 700;
letter-spacing: -.02em;
color: #2c2416;
}
.shk-23b__small {
margin-top: 6px;
font-size: 12.5px;
color: rgba(44,36,22,.55);
}
.shk-23b__shadow {
width: 200px;
height: 12px;
margin-top: 14px;
border-radius: 50%;
background: rgba(0,0,0,.55);
filter: blur(5px);
animation: shk-23b-shadow 3.5s cubic-bezier(.5,0,.7,.3) infinite;
}
.shk-23b__hint {
margin-top: 26px;
font-size: 12px;
color: rgba(230,235,248,.4);
max-width: 420px;
text-align: center;
}
@keyframes shk-23b-thud {
0% {
translate: 0 -120px;
scale: 1 1;
opacity: 0;
}
6% {
opacity: 1;
}
12% {
translate: 0 0;
scale: 1 1;
}
15% {
scale: 1.12 .84;
}
20% {
scale: .96 1.05;
}
25% {
translate: 0 3px;
scale: 1.03 .97;
}
31% {
translate: 0 -1.5px;
scale: 1 1;
}
37% {
translate: 0 1.5px;
}
43% {
translate: 0 -.5px;
}
48%,
86% {
translate: 0 0;
scale: 1 1;
}
100% {
translate: 0 -120px;
opacity: 0;
}
}
@keyframes shk-23b-shadow {
0% {
scale: .45 1;
opacity: .25;
}
12% {
scale: 1 1;
opacity: .8;
}
15% {
scale: 1.15 1;
}
25% {
scale: 1.04 1;
}
48%,
86% {
scale: 1 1;
opacity: .8;
}
100% {
scale: .45 1;
opacity: .25;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23b__card,
.shk-23b__shadow {
animation: none;
}
}
```
## JavaScript
```js
/* No JavaScript — down-frames are large/fast, up-frames small/slow (gravity is asymmetric), each contact squashes via scale with transform-origin at the bottom edge, and the ground line stretches in sympathy on the same clock. */
/* No JavaScript — fall, squash, and shudder are segments of ONE keyframe timeline, with the ground shadow scaling on a matching clock so light and mass agree. Faking physics = choreographing consequences. */
```Here's a working CSS Shake Animation from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Vertical Shake Animation
Source: https://codefronts.com/motion/css-shake-animation/css-vertical-shake-animation/
The vertical axis has different physics: a jackhammer specimen that hammers downward with asymmetric frames (fast down, slow up — impacts are one-sided), and a landing thud where a dropped card hits, compresses, and rings out a decaying vertical shudder with a dust-line flash.
## HTML
```html
<div class="shk-23-group">
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@600..900&family=IBM+Plex+Mono:wght@500;600&display=swap" rel="stylesheet">
<section class="shk-23a" aria-label="Jackhammer vertical shake specimen">
<div class="shk-23a__site">
<p class="shk-23a__permit">PERMIT NO. 23-Y · VERTICAL WORKS</p>
<div class="shk-23a__stage">
<div class="shk-23a__hammer" tabindex="0" aria-label="Hammering block — hover to pause">UNDER<br>CONSTRUCTION</div>
<div class="shk-23a__ground" aria-hidden="true"></div>
</div>
<p class="shk-23a__note">down-strokes 6px & fast · up-strokes 1px & lazy — impacts are one-sided</p>
</div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400..700&display=swap" rel="stylesheet">
<section class="shk-23b" aria-label="Card that drops, thuds and shudders">
<div class="shk-23b__stage">
<div class="shk-23b__card" tabindex="0">
<p class="shk-23b__big">17,4 kg</p>
<p class="shk-23b__small">delivered · signature not required</p>
</div>
<div class="shk-23b__shadow" aria-hidden="true"></div>
<p class="shk-23b__hint" aria-hidden="true">replays every 3.5s (hover to pause) — drop → squash → decaying vertical shudder, one timeline</p>
</div>
</section>
</div>
```
## CSS
```css
.shk-23-group {
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
}
.shk-23-group > section {
flex: 1 1 480px;
min-width: min(100%,360px);
}
.shk-23a,
.shk-23a *,
.shk-23a *::before,
.shk-23a *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23a {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: repeating-linear-gradient(45deg,#f4c81d 0 26px,#191713 26px 52px);
font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
}
.shk-23a__site {
width: min(440px,100%);
padding: 30px 32px 26px;
background: #f7f4ea;
border: 3px solid #191713;
border-radius: 6px;
box-shadow: 10px 10px 0 rgba(25,23,19,.85);
}
.shk-23a__permit {
font-family: 'IBM Plex Mono',ui-monospace,monospace;
font-size: 10.5px;
font-weight: 600;
letter-spacing: .14em;
color: #191713;
border-bottom: 2px dashed rgba(25,23,19,.3);
padding-bottom: 10px;
}
.shk-23a__stage {
margin-top: 26px;
display: grid;
justify-items: center;
}
.shk-23a__hammer {
padding: 22px 30px;
text-align: center;
font-size: 21px;
line-height: 1.15;
font-weight: 900;
letter-spacing: .04em;
color: #f7f4ea;
background: #191713;
border-radius: 4px;
transform-origin: 50% 100%;
animation: shk-23a-hammer .5s linear infinite;
outline: none;
}
.shk-23a__hammer:hover,
.shk-23a__hammer:focus-visible {
animation-play-state: paused;
}
.shk-23a__ground {
width: 78%;
height: 5px;
margin-top: 6px;
background: rgba(25,23,19,.85);
border-radius: 999px;
animation: shk-23a-dust .5s linear infinite;
}
.shk-23a__note {
margin-top: 22px;
font-size: 12px;
font-weight: 600;
color: rgba(25,23,19,.6);
text-align: center;
text-wrap: pretty;
}
@keyframes shk-23a-hammer {
0%,
100% {
translate: 0 0;
scale: 1 1;
}
15% {
translate: 0 6px;
scale: 1.05 .94;
}
35% {
translate: 0 -1px;
scale: 1 1;
}
50% {
translate: 0 5px;
scale: 1.04 .95;
}
70% {
translate: 0 -.5px;
scale: 1 1;
}
85% {
translate: 0 4px;
scale: 1.03 .96;
}
}
@keyframes shk-23a-dust {
0%,
100% {
scale: 1 1;
opacity: .85;
}
15% {
scale: 1.06 1;
opacity: 1;
}
50% {
scale: 1.05 1;
}
85% {
scale: 1.04 1;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23a__hammer,
.shk-23a__ground {
animation: none;
}
}
.shk-23b,
.shk-23b *,
.shk-23b *::before,
.shk-23b *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.shk-23b {
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 100% at 50% 0%,#1b1e26,#101218 65%);
font-family: 'Space Grotesk','Segoe UI',system-ui,sans-serif;
}
.shk-23b__stage {
display: grid;
justify-items: center;
}
.shk-23b__card {
padding: 30px 44px;
text-align: center;
background: linear-gradient(180deg,#f2e8d8,#e2d2b8);
border-radius: 14px;
box-shadow: 0 24px 45px -20px rgba(0,0,0,.75);
transform-origin: 50% 100%;
animation: shk-23b-thud 3.5s cubic-bezier(.5,0,.7,.3) infinite;
outline: none;
}
.shk-23b__card:hover,
.shk-23b__card:focus-visible {
animation-play-state: paused;
}
.shk-23b__big {
font-size: 34px;
font-weight: 700;
letter-spacing: -.02em;
color: #2c2416;
}
.shk-23b__small {
margin-top: 6px;
font-size: 12.5px;
color: rgba(44,36,22,.55);
}
.shk-23b__shadow {
width: 200px;
height: 12px;
margin-top: 14px;
border-radius: 50%;
background: rgba(0,0,0,.55);
filter: blur(5px);
animation: shk-23b-shadow 3.5s cubic-bezier(.5,0,.7,.3) infinite;
}
.shk-23b__hint {
margin-top: 26px;
font-size: 12px;
color: rgba(230,235,248,.4);
max-width: 420px;
text-align: center;
}
@keyframes shk-23b-thud {
0% {
translate: 0 -120px;
scale: 1 1;
opacity: 0;
}
6% {
opacity: 1;
}
12% {
translate: 0 0;
scale: 1 1;
}
15% {
scale: 1.12 .84;
}
20% {
scale: .96 1.05;
}
25% {
translate: 0 3px;
scale: 1.03 .97;
}
31% {
translate: 0 -1.5px;
scale: 1 1;
}
37% {
translate: 0 1.5px;
}
43% {
translate: 0 -.5px;
}
48%,
86% {
translate: 0 0;
scale: 1 1;
}
100% {
translate: 0 -120px;
opacity: 0;
}
}
@keyframes shk-23b-shadow {
0% {
scale: .45 1;
opacity: .25;
}
12% {
scale: 1 1;
opacity: .8;
}
15% {
scale: 1.15 1;
}
25% {
scale: 1.04 1;
}
48%,
86% {
scale: 1 1;
opacity: .8;
}
100% {
scale: .45 1;
opacity: .25;
}
}
@media (prefers-reduced-motion: reduce) {
.shk-23b__card,
.shk-23b__shadow {
animation: none;
}
}
```
## JavaScript
```js
/* No JavaScript — down-frames are large/fast, up-frames small/slow (gravity is asymmetric), each contact squashes via scale with transform-origin at the bottom edge, and the ground line stretches in sympathy on the same clock. */
/* No JavaScript — fall, squash, and shudder are segments of ONE keyframe timeline, with the ground shadow scaling on a matching clock so light and mass agree. Faking physics = choreographing consequences. */
```How this works
Copying a horizontal shake to the Y axis feels wrong because vertical motion carries gravity. Two corrections make it read: asymmetry — down-strokes bigger and faster than up-strokes:
@keyframes hammer{
0%,100%{translate:0 0}
15%{translate:0 6px} /* hit — big, fast */
35%{translate:0 -1px} /* recoil — small */
50%{translate:0 5px} /* hit */
70%{translate:0 -.5px}
85%{translate:0 4px}
}…and consequence — pair the shake with a squash at the moment of contact (scale(1.06,.94)) so mass is conserved. The thud variant chains drop → squash → decaying shudder in one keyframe timeline, which is how you fake physics without a physics engine.
Make it yours
- Down offsets ≈ 2–6× the up offsets — the ground pushes back less than gravity pulls.
- Squash amount tracks amplitude: 6px hammer → scale(1.05,.95); more looks like jelly.
- For continuous machines (jackhammer), loop at 8–12Hz with steps for a mechanical feel.
- For landings, the shudder should decay to nothing within 500ms of first contact — longer reads as an earthquake.
Gotchas — read before shipping
- Vertical shakes near text baselines make copy dance — shake containers, never lines of body text.
- An element that translates down can cover what's below it mid-frame; keep z-index intentional.
- Squash needs transform-origin at the CONTACT edge (bottom) or the element compresses around its center and floats.
- If the element casts a shadow, animate the shadow's blur/offset inversely or the light source appears to move.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by text-wrap as this demo is written. The core technique itself goes back further — Chrome all modern.
Transform-only throughout. transform-origin:bottom for the squash is CSS1-era — everything here degrades to nothing worse than stillness.