Skip to content

Progress

Indeterminate

html
<progress></progress>

Determinate

html
<progress value="10" max="100"></progress>

Circular

Check out the documentation for the spinner.

Accessibility

If the <progress> element is describing the loading progress of a section of a page:

  • use aria-describedby to point to the status
  • set aria-busy="true" on the section that is being updated, removing it when loading is finished.

Source: MDN

Content here is loading.

html
<div aria-busy="true" aria-describedby="progress-bar">
  Content here is loading.
</div>

<progress id="progress-bar" aria-label="Content loading…"></progress>

Installation

css
:where(progress) {
  --_accent-color: var(--primary);
  --_bg-color: var(--surface-tonal);

  appearance: none;
  background-color: var(--_bg-color);
  border-radius: var(--border-radius, 0.25rem);
  border: 0;
  display: inline-block;
  block-size: var(--size-1);
  overflow: hidden;
  position: relative;
  vertical-align: baseline;
  inline-size: 100%;

  &::-webkit-progress-bar {
    border-radius: var(--border-radius, 0.25rem);
    background: none;
  }

  &[value]::-webkit-progress-value {
    background-color: var(--_accent-color);

    @media (prefers-reduced-motion: no-preference) {
      transition: inline-size 0.2s var(--ease-out-4, cubic-bezier(0, 0, 0.1, 1));
    }
  }

  &::-moz-progress-bar {
    background-color: var(--_accent-color);
  }
}

@media (prefers-reduced-motion: no-preference) {
  progress:indeterminate {
    background-color: var(--_bg-color);

    &::after {
      animation: indeterminate 2s linear infinite;
      background-color: var(--_accent-color);
      content: "";
      inset: 0 auto 0 0;
      position: absolute;
      will-change: inset-inline-start, inset-inline-end;
    }

    &[value]::-webkit-progress-value {
      background-color: transparent;
    }

    &::-moz-progress-bar {
      background-color: transparent;
    }
  }
}

[dir="rtl"] {
  :where(progress):indeterminate {
    animation-direction: reverse;
  }
}

[dir="rtl"] {
  :where(progress):indeterminate::after {
    animation-direction: reverse;
  }
}

@keyframes indeterminate {
  0% {
    left: -200%;
    right: 100%;
  }
  60% {
    left: 107%;
    right: -8%;
  }
  100% {
    left: 107%;
    right: -8%;
  }
}