Snippets /

Progress bar

A fully styled <progress> element with gradient fill, rounded corners, and an entrance animation.

Uploading... 72% 72% Compiling... 45% 45%
Widely supported
uianimation

Quick implementation

.progress {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 0.75rem;
  border: none;
  border-radius: 1rem;
  overflow: hidden;
  background: oklch(0.25 0.02 260);
  accent-color: oklch(0.6 0.22 270);
}

.progress::-webkit-progress-bar {
  background: oklch(0.25 0.02 260);
  border-radius: 1rem;
}

.progress::-webkit-progress-value {
  background: linear-gradient(
    90deg,
    oklch(0.55 0.22 270),
    oklch(0.65 0.2 200)
  );
  border-radius: 1rem;
  animation: fill 1.5s ease-out forwards;
}

.progress::-moz-progress-bar {
  background: linear-gradient(
    90deg,
    oklch(0.55 0.22 270),
    oklch(0.65 0.2 200)
  );
  border-radius: 1rem;
  animation: fill 1.5s ease-out forwards;
}

@keyframes fill {
  from { max-width: 0; }
  to { max-width: 100%; }
}

Prompt this to your LLM

Paste this into ChatGPT, Claude, or any code-generating model to scaffold the pattern instantly.

Style the native HTML <progress> element with CSS. Reset
appearance with appearance: none. Style
::-webkit-progress-bar for the track background using
oklch(0.25 0.02 260) and border-radius: 1rem. Style
::-webkit-progress-value with a horizontal linear-gradient
from oklch(0.55 0.22 270) to oklch(0.65 0.2 200). Add the
equivalent ::-moz-progress-bar styles for Firefox. Include
accent-color as a fallback. Add a @keyframes animation that
grows from max-width: 0 to max-width: 100% for an entrance
effect. Set overflow: hidden on the element.

Why this matters

The native <progress> element is semantically correct and accessible out of the box, but its default appearance varies wildly between browsers. Custom styling creates a consistent design while preserving the accessibility benefits. The accent-color fallback ensures even browsers that do not support the pseudo-element selectors still get a branded color.

The logic

First, appearance: none strips the browser's default styling. The ::-webkit-progress-bar pseudo-element styles the track (background), while ::-webkit-progress-value styles the filled portion. Firefox uses ::-moz-progress-bar for the filled portion. Both receive the same gradient and border-radius. The overflow: hidden on the root element clips the filled bar's rounded corners properly. The @keyframes fill animation transitions max-width from 0 to 100% for a smooth entrance when the element enters the viewport.

Accessibility & performance

The <progress> element has an implicit role="progressbar", and browsers automatically expose the current value to assistive technology. Always include fallback text like "72%" between the tags for older browsers. Pair it with a visible label or aria-label describing what is in progress. The animation should be wrapped in @media (prefers-reduced-motion: no-preference) so it is disabled for users who have requested reduced motion. Gradient rendering is GPU-accelerated and has no measurable performance cost.