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