Skip to content
← Spring Animation
Edit Spring Animation
Name
Also known as (comma separated)
Brief definition
Physics-based motion with natural overshoot.
Notes
Tier
Core
Useful
Reference
Deleted
Controls schema (JSON array)
[ { "id": "bounce", "type": "select", "label": "Bounciness", "default": "bouncy", "options": [ "gentle", "bouncy", "wobbly" ] }, { "id": "duration", "type": "number", "label": "Duration (ms)", "default": 900, "min": 300, "max": 2000, "step": 100 }, { "id": "loop", "type": "toggle", "label": "Loop", "default": true }, { "id": "accent", "type": "color", "label": "Colour", "default": "#A8E6C1", "presets": [ "#A8E6C1", "#F5C2E0", "#BFD9F2", "#D9C8F0", "#E8A020", "#241430" ] } ]
Templates (JSON object keyed by format)
{ "html": "<div class=\"mot-spr-stage\" data-bounce=\"{{bounce}}\">\n <div class=\"mot-spr-track\">\n <span class=\"mot-spr-dot{{#if loop}} mot-spr-dot--loop{{/if}}\" style=\"background:{{accent}};\"></span>\n </div>\n <p class=\"mot-spr-caption\">{{bounce}} spring · overshoots then settles, unlike a plain ease</p>\n</div>\n<style>\n.mot-spr-stage { width: 100%; max-width: 320px; padding: 16px; background: #FAF7F2; border: 1px solid #24143022; border-radius: 12px; font: 12px system-ui, sans-serif; color: #241430aa; }\n.mot-spr-track { position: relative; height: 26px; }\n.mot-spr-dot { position: absolute; top: 0; left: 1px; width: 22px; height: 22px; border-radius: 999px; }\n.mot-spr-caption { margin: 10px 0 0; text-transform: capitalize; }\n@media (prefers-reduced-motion: no-preference) {\n .mot-spr-dot { animation-duration: {{duration}}ms; animation-fill-mode: both; }\n [data-bounce=\"gentle\"] .mot-spr-dot { animation-name: mot-spr-gentle; animation-timing-function: cubic-bezier(.25,1.1,.4,1); }\n [data-bounce=\"bouncy\"] .mot-spr-dot { animation-name: mot-spr-bouncy; animation-timing-function: cubic-bezier(.34,1.56,.64,1); }\n [data-bounce=\"wobbly\"] .mot-spr-dot { animation-name: mot-spr-wobbly; animation-timing-function: cubic-bezier(.68,-0.6,.32,1.6); }\n .mot-spr-dot--loop { animation-iteration-count: infinite; }\n @keyframes mot-spr-gentle { from { left: 1px; } to { left: 260px; } }\n @keyframes mot-spr-bouncy { from { left: 1px; } to { left: 260px; } }\n @keyframes mot-spr-wobbly { from { left: 1px; } to { left: 260px; } }\n}\n</style>", "tailwind": "<div class=\"w-full max-w-[320px] p-4 bg-[#FAF7F2] border border-[#24143022] rounded-xl font-sans text-xs text-[#241430]/70\" data-bounce=\"{{bounce}}\">\n <div class=\"relative h-[26px]\">\n <span class=\"absolute top-0 left-px w-[22px] h-[22px] rounded-full{{#if loop}} tw-spr-loop{{/if}}\" style=\"background:{{accent}}; animation-duration:{{duration}}ms; animation-fill-mode:both;\"></span>\n </div>\n <p class=\"mt-2.5 capitalize\">{{bounce}} spring · overshoots then settles, unlike a plain ease</p>\n</div>\n<style>\n@media (prefers-reduced-motion: no-preference) {\n [data-bounce=\"gentle\"] span { animation-name: mot-spr-tw-gentle; animation-timing-function: cubic-bezier(.25,1.1,.4,1); }\n [data-bounce=\"bouncy\"] span { animation-name: mot-spr-tw-bouncy; animation-timing-function: cubic-bezier(.34,1.56,.64,1); }\n [data-bounce=\"wobbly\"] span { animation-name: mot-spr-tw-wobbly; animation-timing-function: cubic-bezier(.68,-0.6,.32,1.6); }\n .tw-spr-loop { animation-iteration-count: infinite; }\n @keyframes mot-spr-tw-gentle { from { left: 1px; } to { left: 260px; } }\n @keyframes mot-spr-tw-bouncy { from { left: 1px; } to { left: 260px; } }\n @keyframes mot-spr-tw-wobbly { from { left: 1px; } to { left: 260px; } }\n}\n</style>", "react": "export function SpringAnimation({\n bounce = \"{{bounce}}\",\n duration = {{duration}},\n loop = {{loop}},\n accent = \"{{accent}}\",\n}) {\n const curves = { gentle: [\"mot-spr-gentle\", \"cubic-bezier(.25,1.1,.4,1)\"], bouncy: [\"mot-spr-bouncy\", \"cubic-bezier(.34,1.56,.64,1)\"], wobbly: [\"mot-spr-wobbly\", \"cubic-bezier(.68,-0.6,.32,1.6)\"] };\n const [name, ease] = curves[bounce];\n return (\n <div style={{ width: \"100%\", maxWidth: 320, padding: 16, background: \"#FAF7F2\", border: \"1px solid #24143022\", borderRadius: 12, fontFamily: \"system-ui, sans-serif\", fontSize: 12, color: \"#241430aa\" }}>\n <div style={{ position: \"relative\", height: 26 }}>\n <span className={loop ? \"dot loop\" : \"dot\"} style={{ position: \"absolute\", top: 0, left: 1, width: 22, height: 22, borderRadius: 999, background: accent }} />\n </div>\n <p style={{ margin: \"10px 0 0\", textTransform: \"capitalize\" }}>{bounce} spring · overshoots then settles, unlike a plain ease</p>\n <style>{`\n @media (prefers-reduced-motion: no-preference) {\n .dot { animation: ${name} ${duration}ms ${ease} 1 both; }\n .dot.loop { animation-iteration-count: infinite; }\n @keyframes mot-spr-gentle { from { left: 1px; } to { left: 260px; } }\n @keyframes mot-spr-bouncy { from { left: 1px; } to { left: 260px; } }\n @keyframes mot-spr-wobbly { from { left: 1px; } to { left: 260px; } }\n }\n `}</style>\n </div>\n );\n}" }
Save
History