11 · Spring Lab: one spring that runs the whole page

Spring Lab is a free motion tool with no client. You tune a single damped spring with stiffness, damping and mass sliders, and every panel, toggle, modal, number and button on the page moves with it. When the feel is right, you copy the easing out as code. What makes people stop is that the page is the preview: drag a slider and the hero letters, the panels and the copy toast all change character.

Inspiration

The main idea comes from Kinetics (kinetics.colorion.co): a spring panel with stiffness, damping and mass sliders and a live preview, plus the Apple-style "duration and bounce" way of describing a spring. The demo pieces come from Motion Primitives (Dock magnification, Sliding Number, Magnetic-style press feedback, toast and dialog). The rig is a set of named common components (modal, toast, drawer, toggle, dock, list, card, number), which is the Component Gallery habit of naming UI parts. MicroKit's small standalone interactions set the scale: each demo is tiny and self-contained. Anime.js v4 and Motion are export targets, not dependencies.

Added on top: the whole page sharing one spring, retargeting that keeps velocity, an oscilloscope with settle time and overshoot, A/B compare against a pinned spring, and five export formats including a sampled CSS linear().

Visual direction

References

Not used from the first list: the WebGL gradient tools, Magic UI, Aceternity, 21st.dev and Cult UI do not show up here. Text Effects and Kage were not used either.

Why these choices

Bright and physical, on purpose. Most of the set is dark and cinematic, and a tool people return to and paste code from suits paper and graph grid better. The single shared spring is the clever part: the sliders change the feel of the page you are standing on, so you do not need to imagine it.

Two solvers do two jobs. A numeric integrator (8 substeps per frame) drives live motion because it can be interrupted mid-flight and keep its velocity. A closed-form solver for under, critical and overdamped cases drives the scope, the stats and the exports, because those need exact values at any time. The trade-off is that two code paths must agree, and the builder checked that they do.

Exporting a spring as CSS linear() needs sampling. The code samples 240 points and thins them with Douglas-Peucker, so the output stays short. Anime.js gets its own spring() call with no sampling. Share links use the URL hash and state also lives in localStorage, wrapped in try/catch.

Cost: it loads Google Fonts, so offline it falls back to system fonts. The spring is integrated in eight substeps per frame, so about 480 steps a second at 60 fps.

Who this kind of site is for

Who would use the tool itself: front-end developers and designers who want a spring feel in plain CSS without shipping a library; motion designers handing values to developers; design-system teams choosing one shared "feel" and writing it into documentation; students learning why damping ratio matters. The use is simple: pick a preset or set bounce and duration, check the scope for overshoot and settle time, use the A/B compare against your current easing, then copy the CSS linear() or the Anime.js or Motion snippet. The share link lets one person send an exact spring to another.

Where this style wins: design-tool sites, motion or design-system documentation, and lead-magnet utilities where a free useful tool earns trust before a sale. It is also a good template for any "calculator that explains itself" page. It is the wrong call for a brochure site for a bakery or contractor, where nobody wants a physics lab and the sliders are noise.

How to make it

Stack and key techniques

The prompt

Build a single-file website, index.html, no libraries and no build step, called "Spring Lab": a free tool that tunes one damped spring and exports it as code. There is no client. Audience: front-end developers and motion designers.

Core idea: ONE shared spring drives every animation on the page. Nothing animated may use CSS easing or transitions: hero letters rising in, panels settling on load, button press squashes, the "Copied" toast, all use the live spring. Moving a slider must change the feel of the whole page.

Look: warm paper #FBF8F1, ink navy #17213D, blueprint blue #1E3FA8, coral #FF5A3C, graph-paper grid background (160px major, 32px minor lines). Fonts from Google Fonts: Bricolage Grotesque (display), Instrument Sans (body), IBM Plex Mono (labels, values, code). Section marks look like rubber stamps (rotated, bordered, with a noise mask). Bright and physical, not dark.

Spring math: write a spring value class using numeric integration (8 substeps per frame, dt clamped to 1/30 s) that keeps its velocity when the target changes. Separately write a closed-form solver for under, critical and overdamped cases that returns value(t), settle time, overshoot percent, damping ratio and natural frequency. Add duration/bounce mapping both ways (Apple style), kept in sync with stiffness, damping, mass and start-velocity sliders.

Layout: hero with the title, three sliding-number readouts of k, c and m (digit strips on springs), and a click-or-drag 2D ball toy with a fading trail canvas. Then a two-column lab: a sticky left tuner (oscilloscope canvas with position and velocity traces, settle marker and a moving playhead; physical sliders; perceptual sliders; twelve presets; "pin current as A") and a right column with: (1) a rig of ten named UI pieces, each with a replay button: modal, toast, drawer, toggle, dock with pointer magnification, staggered list, 3D card flip, sliding number, drag-and-release ball, and an interruption demo; (2) A/B compare running three pieces with the pinned spring against the current one; (3) export tabs: CSS linear() sampled from the real spring and simplified with Douglas-Peucker, Web Animations API, Anime.js v4 spring() importing https://cdn.jsdelivr.net/npm/animejs@4.5.0/+esm, Motion/Framer transition, and an @keyframes fallback, with duration input, copy button and share-link button; (4) three small diagrams explaining k/c/m, the damping regimes and interruption.

State: URL hash plus localStorage (wrapped in try/catch). On phones (under 980px) the tuner becomes normal flow and a sticky mini scope stays under the header.

Constraints: prefers-reduced-motion disables the intro and automatic replays. Keyboard operable: arrow keys move both balls, toggle is a real switch. No horizontal overflow at 360px. Visible focus rings.

Verification loop: open the page, screenshot at 8 scroll stops on desktop and 7 on a phone viewport, check the console for errors, fix and repeat. Prove the export: run each preset's linear() through the Web Animations API and compare against the closed-form spring at several times; it must match within about 0.005 of full travel. Test slider sync, presets, pin A, every export tab, every replay button.

Build notes

Stepping down: what you would likely lose

This is an informed estimate, not a measurement. No public benchmark compares these exact models on one-shot frontend work, and the evidence is spec tables, Anthropic's own pages and earlier-generation reviews, plus extrapolation.

Feature Opus 5.5 (likely outcome) Sonnet 5.5 (likely outcome)
Interruptible spring integrator Does fine, it is a short well-known routine Does fine, likely correct
Closed-form solver with settle and overshoot Does fine, may need a sign check Attempts it with likely bugs: a sign error or a missed critical-damping case
Duration/bounce mapping that stays in sync both ways Does fine Attempts it with likely bugs: sliders fighting each other in a loop
Whole page on one spring, with no CSS easing Does fine, likely with a few leftover transitions Likely simplifies it away: CSS transitions on some pieces
Oscilloscope with velocity, settle marker, mobile mini scope Does fine, mini scope may be less polished Attempts it with likely bugs: blurry canvas on high-DPI or a missing resize redraw
linear() sampling plus Douglas-Peucker, five exports Does fine Attempts it with likely bugs: unsimplified long output or a mismatch with the real spring
Ten demos, including dock, flip, drag with release velocity Does fine, close to Fable 5.1 Likely simplifies it away: fewer demos, drag without release velocity
Visual character (stamps, grid, type pairing) Does fine, slightly more common-looking Likely more template-like

Rough overall estimate, a judgment call: Opus 5.5 keeps roughly 85 to 95 percent of the impact, since the gap to Fable 5.1 is probably small here and the maths is well within reach. Sonnet 5.5 keeps roughly 65 to 80 percent in one pass. The risk is not the look but the maths agreeing with itself across two code paths, and the "everything is on the spring" discipline slipping late in a 700-line file.

What closes the gap: a numeric check script like the builder's proof run (compare exported linear() against the closed form), screenshot feedback on desktop and phone, and splitting the build into the spring core first, then the demos, then export.

← Previous reportNext report →