Creating a Responsive CSS Progress Bar with Transparent Effects in React

Building components in React is always a rewarding experience, especially when the result is sleek, reusable, and visually impressive. Today, I’ll walk you through creating a progress bar in React that is always 100% wide, with a dynamic background that visually represents progress through a transparent effect on the right.

Thank me by sharing on Twitter 🙏

We’ll use CSS and TypeScript to make the component highly customizable and easy to integrate into any project. By the end, you’ll have a progress bar that not only works well but also looks stunning.

Understanding the Requirements

Progress bars are a staple UI element in modern web applications. Whether you’re displaying file uploads, completion percentages, or any other type of progress, a clean design goes a long way toward improving user experience. For this project, the requirements are:

  1. The progress bar should always be 100% wide.
  2. The background should dynamically adjust based on progress.
  3. The filled portion of the bar will be a solid color, while the remaining portion will appear transparent.

We’ll handle the layout with CSS and use React props to make the progress percentage dynamic.

Step 1: Setting Up the Component

We start by creating a React component in TypeScript. The first step is to define the structure of our TransparentBar component.

TypeScript
import React from "react";
import "./TransparentBar.css";

interface TransparentBarProps {
  percentage: number;
}

const TransparentBar: React.FC<TransparentBarProps> = ({ percentage }) => {
  return (
    <div
      className="bar-container"
      style={{
        "--filled-percentage": `${percentage}%`,
      } as React.CSSProperties}
    ></div>
  );
};

export default TransparentBar;

Here’s what’s happening:

  • We define a percentage prop, typed as a number.
  • We use the style attribute to dynamically set a CSS custom property, --filled-percentage, which we’ll use in our CSS file.
  • The className points to a CSS class we’ll define next to style the bar.

By keeping the logic minimal in the React component and offloading the styling to CSS, we achieve a clean separation of concerns.

Step 2: Crafting the CSS

The magic of this progress bar lies in its CSS. With a 100% wide div, the background dynamically adjusts using a linear-gradient to achieve the solid-to-transparent effect.

CSS
.bar-container {
  width: 100%;
  height: 30px; /* Adjust height as needed */
  background: linear-gradient(
    to right,
    blue var(--filled-percentage, 0%),
    transparent var(--filled-percentage, 0%)
  );
  border: 1px solid #000; /* Optional: for visibility */
  position: relative;
}

Let’s break this down:

  1. Dynamic Gradient: The linear-gradient transitions from a solid color (blue) to transparent. The var(--filled-percentage) value determines the point where the transition occurs.
  2. CSS Custom Property: The --filled-percentage variable makes it easy to control the gradient from the React component.
  3. Responsive Design: The width is always set to 100%, so it spans the full width of the container, regardless of the screen size.

Step 3: Integrating the Component

Once the component and styles are in place, it’s time to use the TransparentBar in a parent component. Here’s an example where users can interactively update the progress:

TypeScript
import React, { useState } from "react";
import TransparentBar from "./TransparentBar";

const App: React.FC = () => {
  const [progress, setProgress] = useState<number>(50);

  const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const value = Math.min(100, Math.max(0, parseInt(event.target.value, 10)));
    setProgress(value);
  };

  return (
    <div>
      <h1>Interactive Progress Bar</h1>
      <TransparentBar percentage={progress} />
      <input
        type="number"
        value={progress}
        onChange={handleInputChange}
        style={{ marginTop: "20px", width: "50px" }}
      />
    </div>
  );
};

export default App;

In this example:

  • We use a state variable progress to control the bar’s percentage.
  • An input field allows the user to set the progress value dynamically, with clamping logic to ensure the value stays between 0 and 100.
  • The TransparentBar updates automatically as the state changes.

Step 4: Enhancing with Accessibility

A good progress bar should not only look great but also be accessible to all users. Adding an aria-label and other accessibility features ensures compatibility with screen readers.

Here’s an updated version of our TransparentBar component:

TypeScript
const TransparentBar: React.FC<TransparentBarProps> = ({ percentage }) => {
  return (
    <div
      className="bar-container"
      style={{
        "--filled-percentage": `${percentage}%`,
      } as React.CSSProperties}
      role="progressbar"
      aria-valuenow={percentage}
      aria-valuemin={0}
      aria-valuemax={100}
    ></div>
  );
};

These additional attributes communicate the current progress state to assistive technologies, making the component more inclusive.

Step 5: Customizing the Appearance

One of the benefits of this approach is how easy it is to customize. For instance, changing the color or height of the bar is as simple as modifying the CSS.

To change the bar’s color dynamically based on the percentage, you can extend the logic:

CSS
.bar-container {
  background: linear-gradient(
    to right,
    var(--bar-color, blue) var(--filled-percentage, 0%),
    transparent var(--filled-percentage, 0%)
  );
}

Then, pass the color as a prop and include it in the inline styles:

TypeScript
interface TransparentBarProps {
  percentage: number;
  color?: string;
}

const TransparentBar: React.FC<TransparentBarProps> = ({ percentage, color = "blue" }) => {
  return (
    <div
      className="bar-container"
      style={{
        "--filled-percentage": `${percentage}%`,
        "--bar-color": color,
      } as React.CSSProperties}
    ></div>
  );
};

Now you can customize the bar color like so:

<TransparentBar percentage={75} color="green" />

Conclusion

By combining React’s dynamic capabilities with the power of CSS, we’ve created a progress bar that’s both functional and visually appealing. The use of CSS custom properties makes the component highly reusable and easy to style, while TypeScript ensures type safety and better maintainability.

This approach strikes a balance between simplicity and flexibility, allowing you to integrate the progress bar into any project effortlessly. Whether you’re building a dashboard, an interactive form, or a user feedback interface, this transparent bar design is sure to enhance the user experience.

View the CodeSandbox

Share this:

Leave a Reply