How to Fix Flickering Canvas Animation in JavaScript

Canvas animations are one of the most powerful ways to create dynamic, interactive visuals in the browser. From games and particle effects to complex data visualizations, HTML5 canvas is widely used by developers. But if you’ve ever built one, you’ve probably encountered a common issue: canvas flickering.

In this article, we’ll explore how to fix flickering canvas animation in JavaScript. We’ll walk through why flickering happens, how to prevent it, and best practices for smooth animations. This guide is ideal for beginners and intermediate developers who want clear, clean solutions.

Let’s dive in!


What Is Canvas Flickering?

Canvas flickering refers to a visual glitch where the screen appears to flash, shake, or momentarily display artifacts during animations. This usually occurs when frames are not drawn correctly or when canvas elements are not cleared or updated efficiently.

This can ruin the user experience—especially in animations where smooth transitions are crucial.


Why Does Canvas Flickering Happen?

Before we fix the issue, we need to understand why flickering occurs in canvas animations. Here are some common causes:

  1. Improper clearing of the canvas before redrawing each frame.

  2. Multiple overlapping drawing operations on the same area without clearing.

  3. Incorrect frame timing, causing tearing or partial renders.

  4. CSS scaling or transformations affecting the rendering.

  5. Mixing DOM updates and canvas rendering inefficiently.

All of these contribute to canvas not rendering cleanly, resulting in flickering.


Example of Flickering Canvas Animation

Here’s a basic example of a canvas animation that might flicker:

html
<canvas id="myCanvas" width="500" height="500"></canvas>

<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

let x = 0;

function animate() {
  // Incorrect: not clearing canvas
  ctx.fillStyle = 'red';
  ctx.fillRect(x, 50, 50, 50);
  x += 2;

  requestAnimationFrame(animate);
}

animate();
</script>

In this code, the red square moves to the right—but previous frames are never cleared. This causes the red square to smear across the canvas, which may appear as flickering or ghosting.


How to Fix Flickering Canvas Animation in JavaScript

Let’s walk through step-by-step how to fix flickering canvas animation in JavaScript.


1. Clear the Canvas on Every Frame

One of the most common and effective solutions is to clear the canvas before drawing the next frame.

Update your code like this:

javascript
function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear canvas

  ctx.fillStyle = 'red';
  ctx.fillRect(x, 50, 50, 50);
  x += 2;

  requestAnimationFrame(animate);
}
By using ctx.clearRect(...), you erase the previous frame, ensuring no ghosting or visual artifacts remain. This alone can solve 80% of flickering issues.

2. Use requestAnimationFrame() Correctly

Many developers make the mistake of using setInterval() or setTimeout() for animations. While they can work, they don’t sync with the browser’s refresh rate, which leads to screen tearing or uneven frame rendering.

Always use requestAnimationFrame() for smooth animations:

javascript
function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // drawing logic...
  requestAnimationFrame(draw);
}

requestAnimationFrame(draw);

requestAnimationFrame() automatically syncs with the display refresh rate (usually 60fps), making your canvas animations smoother and preventing flickering.


3. Set Canvas CSS Dimensions Correctly

Improper use of CSS width and height can also cause canvas flickering. Your canvas tag might look like this:

html
<canvas id="canvas" width="600" height="400" style="width: 100%; height: auto;"></canvas>

This can lead to pixel stretching or blurry/flickering visuals. The fix?

Always keep the CSS and HTML dimensions aligned:

html
<canvas id="canvas" width="600" height="400"></canvas>

And don’t override width/height using CSS. If you need to scale the canvas, scale the drawing inside the canvas—not the canvas element itself.


4. Avoid Overlapping Draws Without Clearing

Another common flickering issue happens when developers draw overlapping elements without clearing them. Even if it’s the same object (e.g., a bouncing ball), failing to clear the canvas leads to smudged visuals.

Here’s a clean example:

javascript
let x = 0;

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  ctx.beginPath();
  ctx.arc(x, 100, 30, 0, Math.PI * 2);
  ctx.fillStyle = 'blue';
  ctx.fill();
  
  x += 2;
  requestAnimationFrame(draw);
}

Notice we start with ctx.clearRect() and then draw the circle from scratch—this is the cleanest method to fix flickering canvas animation in JavaScript.


5. Avoid CSS Transitions on Canvas Elements

Applying CSS animations or transitions on canvas elements can conflict with internal redraws, especially if you’re manipulating canvas size or opacity dynamically.

Avoid doing this:

css
canvas {
transition: all 0.3s ease;
}

Instead, control all animations within JavaScript using canvas APIs. This gives you more control and eliminates flickering caused by style transitions.


6. Double Buffering (Advanced Fix)

In graphics programming, double buffering is used to draw on a hidden canvas, then copy the final result to the visible one. This ensures that users never see the canvas during a half-rendered state.

Here’s an example:

javascript
const offscreen = document.createElement('canvas');
offscreen.width = canvas.width;
offscreen.height = canvas.height;
const offCtx = offscreen.getContext('2d');

function draw() {
  offCtx.clearRect(0, 0, canvas.width, canvas.height);

  offCtx.fillStyle = 'green';
  offCtx.fillRect(x, 50, 50, 50);

  // Copy offscreen canvas to main canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(offscreen, 0, 0);

  x += 3;
  requestAnimationFrame(draw);
}

Double buffering minimizes screen tearing and flickering, especially useful for high-FPS animations or games.


Bonus: Combine with Debounced Scroll

Sometimes flickering occurs not because of canvas logic but due to other browser events triggering repaints, like scroll.

In that case, it’s smart to debounce scroll events to prevent performance issues. We’ve covered this in detail in our debounce scroll event guide.


Best Practices to Fix Flickering Canvas Animation in JavaScript

To summarize, here are key practices to follow:

✅ Clear the canvas using clearRect() every frame
✅ Always use requestAnimationFrame()
✅ Match canvas HTML and CSS dimensions
✅ Avoid CSS transitions on <canvas>
✅ Redraw from scratch every frame
✅ Consider double buffering for complex visuals
✅ Optimize related events (scroll, resize)

Following these will eliminate most causes of canvas flickering.


Real World Example: Particle Animation

Let’s apply all these best practices in a real example. We’ll animate a simple particle system that moves without flickering.

html
<canvas id="canvas" width="500" height="300"></canvas>

<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let particles = [];

for (let i = 0; i < 50; i++) {
  particles.push({
    x: Math.random() * canvas.width,
    y: Math.random() * canvas.height,
    dx: (Math.random() - 0.5) * 2,
    dy: (Math.random() - 0.5) * 2,
    radius: Math.random() * 4 + 1,
  });
}

function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  particles.forEach(p => {
    p.x += p.dx;
    p.y += p.dy;

    if (p.x < 0 || p.x > canvas.width) p.dx *= -1;
    if (p.y < 0 || p.y > canvas.height) p.dy *= -1;

    ctx.beginPath();
    ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
    ctx.fillStyle = 'purple';
    ctx.fill();
  });

  requestAnimationFrame(animate);
}

animate();
</script>

This simple particle system is flicker-free, fast, and runs at 60fps because it follows all the techniques mentioned above.


Final Thoughts

Flickering canvas animations can frustrate both developers and users—but the good news is that they’re easily fixable with the right techniques.

In this guide, we explored how to:

  • Diagnose the root cause of canvas flickering

  • Apply clearRect() properly

  • Use requestAnimationFrame() instead of setInterval

  • Keep canvas sizes in sync with CSS

  • Optimize redraw logic and reduce overlapping

  • Use double buffering for clean frame swaps

By following these principles, you’ll create smooth, high-performance animations with HTML5 canvas.

Remember, performance issues in web animations often come down to drawing too much, too fast, or inefficiently. With proper logic and best practices, you can easily fix flickering canvas animation in JavaScript.

If you’re also working with scroll-based animations, be sure to check out our guide on how to debounce scroll events, which helps avoid frame drops and visual glitches from scroll-triggered canvas repaints.


Leave a Reply