Frontend Development 11 min read

Optimizing a React Progress Bar Component: From Inefficient Implementation to GPU‑Accelerated Performance

This article examines a common React progress‑bar component, explains why the naïve timer‑based implementation causes heavy reflows and repaints, and presents a GPU‑accelerated CSS animation solution that dramatically improves frame rates and reduces layout work.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Optimizing a React Progress Bar Component: From Inefficient Implementation to GPU‑Accelerated Performance

In the introduction the author, a front‑end developer, shares a progress‑bar component he found in a project and points out that, while functionally correct, it suffers from serious performance problems caused by frequent state updates.

The component is typically used in video‑playback scenarios (e.g., TikTok‑style short videos) where the bar must grow with the video length and pause when the video is paused.

Problematic implementation (React + timer)

// index.jsx
import { useState } from 'react';
import './index.css';

let timer = null; // timer that increments progress
let totalTime = 3000; // assume video length is 3 s

function App() {
  const [progress, setProgress] = useState(0); // progress
  const [isPlay, setIsPlay] = useState(false); // playing flag

  const handlerProgress = pre => {
    if (pre < 100) return pre + 1;
    else {
      alert('播放结束');
      return 0; // restart after finish
    }
  };

  const handleVideo = () => {
    setIsPlay(!isPlay);
    isPlay ? clearInterval(timer) : timer = setInterval(() => setProgress(handlerProgress), totalTime / 100);
  };

  const replay = () => {
    setIsPlay(true);
    if (timer) clearInterval(timer);
    setProgress(0);
    timer = setInterval(() => setProgress(handlerProgress), totalTime / 100);
  };

  return (
{ isPlay ? '暂停' : '播放' }
重播
);
}

The CSS for the above version simply defines a container and a red bar whose width is updated via the progress state, causing the browser to recalculate layout on every tick, which leads to noticeable jank.

Why this approach is slow

Each change to progress triggers a React re‑render, which updates the width style of the bar. Changing width forces the browser to perform layout (reflow) and paint (repaint) on every frame, resulting in heavy CPU usage and low FPS.

Recommended implementation (CSS animation + GPU acceleration)

// index.jsx
import { useState } from 'react';
import './index.css';

let totalTime = 3000; // 3 s video

function App() {
  const [isPlay, setIsPlay] = useState(false);
  const [count, setCount] = useState(0);
  const [type, setType] = useState(0); // 0: play, 1: replay

  const handleVideo = () => setIsPlay(!isPlay);

  const replay = () => {
    setIsPlay(true);
    setType(type ? 0 : 1);
  };

  const end = () => {
    setCount(count + 1);
    replay();
  };

  return (
{ isPlay ? '暂停' : '播放' }
重播
{ `播放次数为:${count}` }
);
}

The accompanying CSS uses two @keyframes (play and replay) that animate the transform property instead of width . By animating scaleX and translateX , the browser can off‑load the work to the GPU, avoiding layout thrashing.

@keyframes play {
  0% { transform: translateX(-50%) scaleX(0); }
  to { transform: translateX(0) scaleX(1); }
}
@keyframes replay {
  0% { transform: translateX(-50%) scaleX(0); }
  to { transform: translateX(0) scaleX(1); }
}
.container {
  height: 10px;
  border-radius: 5px;
  border: 1px solid black;
}
.progress {
  height: 100%;
  width: 100%; /* start at full width, then scale */
  background-color: red;
  will-change: transform;
  animation-timing-function: linear;
}
.progress.play { animation-play-state: running; }
.progress.pause { animation-play-state: paused; }

Because the animation only modifies transform , the browser creates a separate compositing layer for the bar, eliminating most reflows and repaints. The author validates the improvement with Chrome DevTools Performance, showing a reduction of layout work and a stable FPS of 55‑70 compared to 32‑50 for the timer‑based version.

In real‑world projects with more complex pages, the same technique can yield performance gains well beyond the 40‑54 % measured on this minimal demo.

Finally, the article includes a “small easter egg” showing how to inspect the new GPU layer using Chrome DevTools Layers, confirming that the progress bar is now rendered on its own layer.

frontendperformance optimizationreactGPU AccelerationCSS animationprogress bar
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.