Skip to main content

Progress Bar

<sl-progress-bar> | SlProgressBar
Since 1.0 stable

Progress bars are used to show the status of an ongoing operation.

<sl-progress-bar value="50"></sl-progress-bar>

Examples

Label Position

Use the label-position attribute to control how labels are displayed. Valid values include top, inner-left, inner-right, and none.

Loading…
50%
<div class="progress-bar-examples">
  <sl-progress-bar
    value="50"
    label-position="top">
    <div slot="leading-label">Loading...</div>
    <div slot="trailing-label">50%</div>
  </sl-progress-bar>

  <sl-progress-bar
    value="50"
    label-position="inner-left"
    show-indicator-value>
  </sl-progress-bar>

  <sl-progress-bar
    value="50"
    label-position="inner-right"
    show-indicator-value>
  </sl-progress-bar>

  <sl-progress-bar
    value="50"
    label-position="none">
  </sl-progress-bar>
</div>

<style>
  .progress-bar-examples {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }
</style>

Custom Labels

Use the leading-label and trailing-label properties or slots to add labels above the progress bar. Custom HTML can be used in the leading-label and trailing-label slots.

Loading files…
50%
Transfer progress
3 of 4 files
75%
<div class="custom-label-examples">
  <sl-progress-bar value="50">
    <div slot="leading-label">Loading files...</div>
    <div slot="trailing-label">50%</div>
  </sl-progress-bar>

  <sl-progress-bar value="75">
    <div slot="leading-label">
      <strong>Transfer progress</strong>
      <div style="font-size: 0.8em; opacity: 0.8;">3 of 4 files</div>
    </div>
    <div slot="trailing-label">
      <sl-tag variant="success">75%</sl-tag>
    </div>
  </sl-progress-bar>

  <sl-progress-bar value="5">
    <div slot="leading-label">
      <sl-data-pair-tile align="left" label="Received amount" value="6000" value-type="currency"></sl-data-pair-tile>
    </div>
    <div slot="trailing-label">
      <sl-data-pair-tile align="right" label="Expected amount" value="120000" value-type="currency"></sl-data-pair-tile>
    </div>
  </sl-progress-bar>
</div>

<style>
  .custom-label-examples {
    display: flex;
    flex-direction: column;
    gap: 2rem;
  }
</style>

Showing Values Inside the Bar

There are two ways the value can be shown inside the indicator bar:

Inner Left (centered)

Inner Right (right aligned)

Custom Format

Dynamic Progress

Start Progress
<div class="internal-value-examples">
  <h4>Inner Left (centered)</h4>
  <div class="dynamic-progress">
    <sl-progress-bar value="0" label-position="inner-left" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="6" label-position="inner-left" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="7" label-position="inner-left" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="10" label-position="inner-left" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="99" label-position="inner-left" show-indicator-value></sl-progress-bar>
  </div>

  <h4>Inner Right (right aligned)</h4>
  <div class="dynamic-progress">
    <sl-progress-bar value="0" label-position="inner-right" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="6" label-position="inner-right" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="89" label-position="inner-right" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="92" label-position="inner-right" show-indicator-value></sl-progress-bar>
    <sl-progress-bar value="93" label-position="inner-right" show-indicator-value></sl-progress-bar>
  </div>

  <h4>Custom Format</h4>
    <sl-progress-bar value="50" label-position="inner-left" show-indicator-value indicator-format="Loading {value}%"></sl-progress-bar>

  <h4>Dynamic Progress</h4>
  <div id="dynamic-progress" style="margin-bottom: 1rem;">
    <sl-progress-bar value="0" label-position="inner-left" show-indicator-value></sl-progress-bar>
  </div>
  <sl-button id="start-progress" style="width: 120px;">Start Progress</sl-button>

  <script>
    const progressBar = document.querySelector('#dynamic-progress sl-progress-bar');
    const startButton = document.querySelector('#start-progress');
    
    startButton.addEventListener('click', () => {
      progressBar.value = 0;
    
      const interval = setInterval(() => {
        progressBar.value += 1;
        
        if (progressBar.value >= 100) {
          clearInterval(interval);
        }
      }, 100);
    });
  </script>
</div>

<style>
  .internal-value-examples {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }

  .dynamic-progress {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
  }

  h4 {
    margin-bottom: 0.5rem;
    margin-top: 0.5rem;
  }
</style>

Standard Sizes

The progress bar can be sized using the --height CSS property. Here are examples of standard sizes:

Standard Progress Bars

Small (4px)
Medium (8px) - Default
Large (12px)

With Internal Labels

<div class="size-examples">
  <h4>Standard Progress Bars</h4>
  <sl-progress-bar value="50" style="--height: 4px;" label-position="top">
    <div slot="leading-label">Small (4px)</div>
  </sl-progress-bar>
  <sl-progress-bar value="50" style="--height: 8px;" label-position="top">
    <div slot="leading-label">Medium (8px) - Default</div>
  </sl-progress-bar>
  <sl-progress-bar value="50" style="--height: 12px;" label-position="top">
    <div slot="leading-label">Large (12px)</div>
  </sl-progress-bar>

  <h4>With Internal Labels</h4>
  <sl-progress-bar value="50" style="--height: 18px;" label-position="inner-left" show-indicator-value></sl-progress-bar>
  <sl-progress-bar value="50" style="--height: 24px;" label-position="inner-left" show-indicator-value></sl-progress-bar>
  <sl-progress-bar value="50" style="--height: 30px;" label-position="inner-left" show-indicator-value></sl-progress-bar>
</div>

<style>
  .size-examples {
    display: flex;
    flex-direction: column;
    gap: 1rem;
  }
</style>

Custom Height

The height can also be be customised using the custom property –height for more precision.

Tiny (2px)
<div class="height-examples">  
  <sl-progress-bar value="50" style="--height: 2px;" label-position="top">
    <div slot="leading-label">Tiny (2px)</div>
  </sl-progress-bar>

  <sl-progress-bar value="50" style="--height: 70px;" label-position="inner-left" show-indicator-value></sl-progress-bar>
</div>

<style>
  .height-examples {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }
</style>

Showing Values

Use the default slot to show a value.

50%
<sl-progress-bar value="50" class="progress-bar-values">50%</sl-progress-bar>

<br />

<sl-button circle><sl-icon name="dash" label="Decrease"></sl-icon></sl-button>
<sl-button circle><sl-icon name="plus" label="Increase"></sl-icon></sl-button>

<script>
  const progressBar = document.querySelector('.progress-bar-values');
  const subtractButton = progressBar.nextElementSibling.nextElementSibling;
  const addButton = subtractButton.nextElementSibling;

  addButton.addEventListener('click', () => {
    const value = Math.min(100, progressBar.value + 10);
    progressBar.value = value;
    progressBar.textContent = `${value}%`;
  });

  subtractButton.addEventListener('click', () => {
    const value = Math.max(0, progressBar.value - 10);
    progressBar.value = value;
    progressBar.textContent = `${value}%`;
  });
</script>

Indeterminate

The indeterminate attribute can be used to inform the user that the operation is pending, but its status cannot currently be determined. In this state, value is ignored and the label, if present, will not be shown.

<sl-progress-bar indeterminate></sl-progress-bar>

Effects

There are two built-in effects, sheen and pulse. Effects are intentionally subtle, as they can be distracting when used extensively. The default is none, which displays a static, non-animated progress bar.

None (default)

Sheen

Pulse

<div class="progress-bar-effects">
  <div>
    <h4>None (default)</h4>
    <sl-progress-bar effect="none" value="50"></sl-progress-bar>
  </div>
  
  <div>
    <h4>Sheen</h4>
    <sl-progress-bar effect="sheen" value="50"></sl-progress-bar>
  </div>
  
  <div>
    <h4>Pulse</h4>
    <sl-progress-bar effect="pulse" value="50"></sl-progress-bar>
  </div>
</div>

<style>
  .progress-bar-effects {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }
  
  h4 {
    margin-bottom: 0.5rem;
    margin-top: 0.5rem;
  }
</style>

Slots

Name Description
(default) A label to show inside the progress indicator.
leading-label A custom label that appears first in the label container.
trailing-label A custom label that appears after in the label container.

Learn more about using slots.

Properties

Name Description Reflects Type Default
value The current progress as a percentage, 0 to 100. number 0
indeterminate When true, percentage is ignored, the label is hidden, and the progress bar is drawn in an indeterminate state. boolean false
label A custom label for assistive devices. string ''
labelPosition
label-position
The label position: top, inner-left, inner-right, or none 'top' | 'inner-left' | 'inner-right' | 'none' 'top'
showIndicatorValue
show-indicator-value
Whether to show the indicator value boolean false
indicatorFormat
indicator-format
Optional format for the indicator value string '{value}%'
effect Determines which effect the progress bar will use. 'pulse' | 'sheen' | 'none' 'none'
updateComplete A read-only promise that resolves when the component has finished updating.

Learn more about attributes and properties.

Custom Properties

Name Description Default
--height The progress bar’s height.
--track-color The color of the track.
--indicator-color The color of the indicator.
--label-color The color of the label.
--sheen-color The sheen color when the skeleton is in its loading state.

Learn more about customizing CSS custom properties.

Parts

Name Description
base The component’s base wrapper.
indicator The progress bar’s indicator.
label The progress bar’s label.
leading-label The leading label container.
trailing-label The trailing label container.
indicator-value The container for the indicator value.

Learn more about customizing CSS parts.