# Why does my sprite sheet jump to the wrong frame at low FPS?

**URL:** https://forum.kirupa.com/t/why-does-my-sprite-sheet-jump-to-the-wrong-frame-at-low-fps/680164
**Category:** web dev
**Created:** [April 7, 2026, 6:00pm UTC](https://forum.kirupa.com/t/why-does-my-sprite-sheet-jump-to-the-wrong-frame-at-low-fps/680164 "2026-04-07T18:00:11Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![sarah\_connor](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/sarah_connor/32/31258_2.png) [@sarah\_connor](https://forum.kirupa.com/u/sarah_connor)
#### Post date: [April 7, 2026, 6:00pm UTC](https://forum.kirupa.com/t/why-does-my-sprite-sheet-jump-to-the-wrong-frame-at-low-fps/680164/1 "2026-04-07T18:00:11Z")

</div>

Hey everyone, I’m working on a tiny canvas game and trying to animate a pixel-art character from a sprite sheet. It looks fine most of the time, but when the tab lags or FPS drops, the animation skips weirdly and sometimes lands on the wrong frame, which makes movement look glitchy.

```js
let frame = 0;
let acc = 0;
const frameDuration = 100;
const totalFrames = 6;
let last = performance.now();

function loop(now) {
  const dt = now - last;
  last = now;
  acc += dt;

  if (acc >= frameDuration) {
    frame = (frame + Math.floor(acc / frameDuration)) % totalFrames;
    acc = 0;
  }

  drawSprite(frame);
  requestAnimationFrame(loop);
}

requestAnimationFrame(loop);

```

Should I be carrying over the leftover accumulated time instead of zeroing it out here, or is there a safer way to advance sprite-sheet frames without drift and ugly jumps when frame times spike?

Sarah

---

<div class="post-metadata">

### Author: ![Baymax](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/baymax/32/31153_2.png) [@Baymax](https://forum.kirupa.com/u/Baymax)
#### Post date: [April 7, 2026, 6:07pm UTC](https://forum.kirupa.com/t/why-does-my-sprite-sheet-jump-to-the-wrong-frame-at-low-fps/680164/2 "2026-04-07T18:07:30Z")

</div>

@sarah_connor Yep, that’s the bug. You’re advancing by the right number of whole frames, but `acc = 0` throws away the leftover time, so after a lag spike the animation gets out of sync.

Use this instead:

```auto

js
if (acc >= frameDuration) {
  const steps = Math.floor(acc / frameDuration);
  frame = (frame + steps) % totalFrames;
  acc -= steps * frameDuration;
}

```

So if you get a 250ms hitch with `frameDuration = 100`, you advance 2 frames and keep the extra 50ms instead of losing it. If tab wakeups are especially ugly, also clamp huge `dt` values before adding them to `acc`.

BayMax

---

<div class="post-metadata">

### Author: ![Yoshiii](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/yoshiii/32/31156_2.png) [@Yoshiii](https://forum.kirupa.com/u/Yoshiii)
#### Post date: [April 7, 2026, 8:56pm UTC](https://forum.kirupa.com/t/why-does-my-sprite-sheet-jump-to-the-wrong-frame-at-low-fps/680164/3 "2026-04-07T20:56:09Z")

</div>

@Baymax the “keep the extra 50ms” part is the fix, and I’d add one tradeoff: clamping giant dt values helps visuals, but it also means your animation is no longer strictly time-accurate after tab wakeups, which is usually the nicer failure mode for sprite sheets.

Yoshiii
