Browser animation timing is limited by the refresh rate (typically 60fps). But with a bit of creative hacking, we can simulate sub-frame interpolation — making animations feel smoother than the frame rate allows. This guide uses GSAP and Web Workers to blend physics-calculated positions with the current render frame, unlocking ultra-fluid motion.
Why Sub-Frame Interpolation?
Even with requestAnimationFrame
, you’re capped at ~16.7ms updates. For high-speed or high-precision visuals (e.g. physics, UI drag), this isn’t enough. We’ll decouple physics updates and blend them at render-time for “in-between” values.
Step 1: Spawn a Web Worker for Physics Updates
This runs physics logic independently of the main render loop.
// physics.worker.js
let x = 0, v = 0.1;
function step() {
x += v;
postMessage({ x });
setTimeout(step, 5); // ~200Hz physics loop
}
onmessage = (e) => {
if (e.data === 'start') step();
};
Step 2: Set Up the Main Thread Animation Loop
We'll interpolate between the last two physics values.
const worker = new Worker('physics.worker.js');
let current = 0, previous = 0, alpha = 0;
worker.onmessage = ({ data }) => {
previous = current;
current = data.x;
};
worker.postMessage('start');
function animate(timestamp) {
alpha += 0.05;
if (alpha > 1) alpha = 1;
const interpolated = previous * (1 - alpha) + current * alpha;
gsap.set("#ball", { x: interpolated * 300 });
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Step 3: Render the Element
Basic HTML + CSS to visualize it:
How It Works
The worker calculates the next physics state ~200 times per second, storing the last and current positions. On the main thread, we interpolate between those two values each frame to simulate in-between states. The result is smoother perceived motion without locking to the frame rate.
Pros and Cons
✅ Pros
- Visibly smoother animations under heavy load
- Offloads calculations to Web Workers
- Works great for physics-based UI or motion trails
⚠️ Cons
- Added complexity with worker communication
- Interpolation logic must be carefully tuned
- Minimal benefit for low-speed animations
🚀 Alternatives
- Motion Canvas: For timeline-based animation precision
- requestIdleCallback: Alternative low-priority updates
- PixiJS: Built-in ticker with interpolation hooks
Summary
If your animation feels choppy despite using the best libraries, try interpolating between high-frequency physics values. It gives an illusion of more frames without actually drawing more — a smart trick straight from game engines to your browser.
If this was useful, you can support me here: buymeacoffee.com/hexshift