Interactive Web Motion
Add playful, modern, accessible interactions to a website or GitHub Pages docs site: SVG shapes that morph on hover (circle → star → flower → blob), a cursor-reactive hero field of pastel shapes, text scramble, blur-in scroll reveals, count-up stats, magnetic buttons, tilt + spotlight cards, marching-ants borders, marquees, drifting aurora backgrounds and film grain, from one dependency-free motion-kit.js + motion-kit.css driven by data attributes. Use whenever someone wants a site to feel alive, modern, fun or less static, wants hover animations, morphing SVGs or effects like graphify.com, Stripe or Linear, asks for an animated hero, landing page polish, micro-interactions, scroll animations or a pastel redesign, or wants to upgrade Astro/MkDocs/plain-HTML docs or a GitHub Pages site visually, even if they don't name a library.
At a glance
- Kind
- Skill · Ananke
skill - Reference
neo-pragnya/interactive-web-motion·ananke://skill/neo-pragnya/interactive-web-motion@1.0.0- Files
- 7 · 42.8 KB
- How it's used
- Skills load on demand: the agent sees this skill's name and description, and opens SKILL.md (and any bundled references or scripts) when a task matches.
Documentation
View upstream ↗Contents
Give a static site a living, tactile feel without a framework or a bundle-size hit. One small script
(assets/motion-kit.js, ~12 KB unminified, no dependencies) and one stylesheet (assets/motion-kit.css) power
everything through data attributes, so the same kit drops into Astro, MkDocs, Hugo, Jekyll or hand-written HTML.
Open assets/gallery.html in a browser to see and feel every effect before choosing.
The toolkit
| Effect | Markup | Use it for |
|---|---|---|
| Morphing shape | <svg viewBox="0 0 100 100" data-morph="circle>star"></svg> | icons on cards, nav, buttons; the shape changes when its link/button is hovered or focused |
| Cycling shape | data-morph="circle star hex flower" (+ data-morph-auto="2400") | logos, empty states, playful accents |
| Shape field | <canvas data-field="36"></canvas> inside a position:relative hero | hero backgrounds: pastel shapes drift, flee the pointer and morph when it comes near |
| Text scramble | <h1 data-scramble>Title</h1> | headings, CTA labels (resolves left → right; aria-label keeps the real text) |
| Scroll reveal | <div data-reveal style="--d:.1s"> | sections and cards: fade + un-blur + rise, staggered by --d |
| Count-up | <span data-countup>968</span> | stats |
| Magnetic | <a data-magnetic> | primary buttons |
| Tilt + spotlight | <div data-tilt> | cards (sets --mx/--my for a light that follows the pointer) |
| Marching ants | class="ants" (+ --mk-ants: colour) | dashed animated outline on hover/focus, graphify-style |
| Marquee | <div data-marquee><div>…</div><div aria-hidden="true">…same…</div></div> | logos, sources, tags |
| Aurora | <div class="mk-aurora" style="--mk-aurora-a:…;--mk-aurora-b:…"> | soft drifting colour behind a hero |
| Grain | <body class="mk-grain"> | subtle film texture over flat pastel backgrounds |
Shapes available: circle square squircle triangle diamond hex octagon star star4 star6 spark flower flower4 flower8 blob blob2 blob3 cloud gear. Add more with MotionKit.registerShape(name, theta => radius).
How the morphing works (and why it’s smooth)
Every shape is a radius function r(θ), sampled at the same 120 angles and normalised to 0–1. Morphing is
just interpolating 120 numbers. Any shape can become any other with no point-matching problems (the usual
reason SVG path morphing needs heavy libraries like flubber or GSAP MorphSVG). The points are drawn as a closed
Catmull-Rom spline, which gives polygons softly rounded corners: a friendly, modern look. Read
references/patterns.md before adding new effects.
Workflow
- Pick a palette and a personality. Pastels on a warm off-white read as modern and welcoming: crimson-orange
#ff7a59, lemon#ffd84d, chartreuse#b5e655, turquoise#46d1c6, lilac#a78bfa, sky#7cc4ff, pink#ff8fb1on#fffaf0. Use the saturated colour for shapes, borders and fills. For text on pastel backgrounds use a darker ink of the same hue (contrast ≥ 4.5:1), never the pastel itself. Seereferences/patterns.md› Colour. - Install the kit into the site:
Then load it once in the base layout:python scripts/install_motion_kit.py <site-dir> # Astro: copies to <site>/public/motion-kit/ python scripts/install_motion_kit.py <dir> --plain # plain HTML / MkDocs: copies next to your assets
(In Astro, prefix with<link rel="stylesheet" href="/motion-kit/motion-kit.css" /> <script src="/motion-kit/motion-kit.js" defer></script>import.meta.env.BASE_URLfor GitHub Pages project sites.) - Choose 3–5 effects, not all twelve. A good default:
- hero:
mk-aurora+canvas[data-field]+h1[data-scramble] - every card: a
svg[data-morph]glyph +data-reveal - stats:
data-countup - primary CTA:
data-magnetic+ants
- hero:
- Give each content type a shape. Map categories to shape pairs (rest → hover) and colours, e.g. skill
blob>star, agentcircle>flower, pluginhex>spark. Repeat the same mapping everywhere (cards, chips, page headers) so the shapes become a visual language. - Verify (see below), including reduced motion and a phone-width check.
Accessibility and performance rules
- Everything honours
prefers-reduced-motion. Reveals show instantly, morphs jump, the field draws one still frame, and marquees and auroras stop. Never bypass this. - Content is never hidden without JS: the reveal styles only apply after the script adds
mk-ready. - Decorative SVG and canvas need
aria-hidden="true". Scrambled text keeps its real text inaria-label. - The field pauses when off-screen (IntersectionObserver) and caps device-pixel-ratio at 2.
- Elements visible at load are revealed directly; the observer only handles elements below the fold.
- Keep motion short (≤ 800 ms) and use one easing everywhere (
cubic-bezier(.22,1,.36,1)).
Verify
# 1. Screenshots with frames running (hero field, morph glyphs, reveals)
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless=new --hide-scrollbars \
--virtual-time-budget=4000 --window-size=1400,1800 --screenshot=out.png http://localhost:4321/
# 2. Static mode (what reduced-motion users get, and deterministic for diffs)
…same… "http://localhost:4321/?motion=static"
# 3. Phone width: render the page in a 390px iframe (headless Chrome enforces a ~500px minimum window)
--dump-domproduces only one animation frame, so to test interaction logic, dispatch events and assert in?motion=staticmode (morphs apply instantly). Seereferences/verification.md.- Check both colour schemes if the site has a theme toggle.
Files
| Path | What |
|---|---|
assets/motion-kit.js | the runtime (auto-inits; window.MotionKit API: init, settle, registerShape, pathFor, shapes) |
assets/motion-kit.css | reveal, ants, marquee, aurora, grain, tilt spotlight, reduced-motion rules |
assets/gallery.html | live demo of every effect, also a visual test |
scripts/install_motion_kit.py | copy the kit into a site |
references/patterns.md | design patterns, colour, shape language, do and don’t |
references/verification.md | headless screenshot, static-mode and interaction tests |