<u-progress>
<u-progress> lets you indicatate the amount of completed work, typically displayed as a progress bar.
Quick intro:
- Use the
maxattribute to change the amount of total work to be done - Use the
valueattribute to change the amount of completed work - Remove the
valueattribute to change to indeterminate/unknown amount of work - MDN Web Docs: <progress> (HTMLProgressElement)
Example
<u-progress aria-label="Loading" value="7.5" max="10"></u-progress> <br> <u-progress aria-label="Loading"></u-progress>
Install
npm add -S @u-elements/u-progresspnpm add -S @u-elements/u-progressyarn add @u-elements/u-progressbun add -S @u-elements/u-progress<script type="module" src="https://unpkg.com/@u-elements/u-progress@latest/dist/u-progress.js"></script>Attributes and props
<u-progress>
- Attributes: all global HTML attributes such as
id,class,data-maxcan contain amount of total work to be done. Must be a valid number greater than 0. Defaults to 1.valuecan contain amount of completed work. If present,valuemust be a valid number between 0 andmax. If there is novalueattribute, the progress bar is indeterminate; indicating work is being done, but withouth knowing of how long it will take.
- DOM interface:
HTMLProgressElementHTMLProgressElement.maxreturnsnumberreflectingmaxattributeHTMLProgressElement.positionreturnsnumberbetween 0 and 1 reflecting the calculationvalue / maxHTMLProgressElement.valuereturnsnumberreflectingvaluevalue attributeHTMLProgressElement.labelsreturnsNodeListOf<HTMLLabelElement>
Using Preact?
Setting the value property to null does not remove the value attribute in Preact. Remove through a ref instead: ref={(el) => value === null && el?.removeAttribute("value")}
Styling
Styling the value bar
Currently, there are no standardized pseudo-element selectors specifically designated for <progress> elements (all existing selectors include a ::-vendor- prefix). Consequently, <u-progress> simply renders its value bar using a ::before pseudo-element:
<u-progress aria-label="Loading" class="my-progress" value="6" max="10"></u-progress>
<style>
/* Styling just for example: */
.my-progress {
border-radius: 9em;
border: 1px solid gray;
background: gainsboro;
}
.my-progress::before {
background: tomato;
}
</style>
Styling the indeterminate state
Replicating the native CSS pseudo-class :indeterminate is not possible. Instead, use the selector :not([value]), which is functionally identical, and compatible with both <u-progress> and native <progress>. Example:
.my-progress:not([value]) {
/* Your indeterminate styling here */
}Labeling
In most cases you should provide an accessible label when using <u-progress>. While you can use the standard ARIA labelling attributes aria-labelledby or aria-label, when using <u-progress> you can alternatively use the <label> element.
Server side rendering
You can server side render <u-progress> by using Declarative Shadow DOM.
Styling and markup needed is exported as UHTMLProgressShadowRoot. Example:
import { UHTMLProgressShadowRoot } from '@u-elements/u-progress';
const renderToStaticMarkup = (value?: number, max?: number) =>
`<u-progress
${value ? ` value="${value}"` : ''}
${max ? ` max="${max}"` : ''}
>
${UHTMLProgressShadowRoot}
</u-progress>`Hydration: Attributes are dynamically added in the browser, so the client DOM will differ from the server markup. Use suppressHydrationWarning in React, data-allow-mismatch="attribute" in Vue, or similar for your framework on these elements, to avoid hydration warnings.
Accessibility
| Screen reader | <progress> | <u-progress> |
|---|---|---|
| VoiceOver (Mac) + Chrome | ✅ | ✅ |
| VoiceOver (Mac) + Edge | ✅ | ✅ |
| VoiceOver (Mac) + Firefox | ✅ | ✅ |
| VoiceOver (Mac) + Safari | ✅ | ✅ |
| VoiceOver (iOS) + Chrome | ❌ Does not announce value | ✅ |
| VoiceOver (iOS) + Safari | ❌ Announces value, but not related max | ✅ |
| Jaws (PC) + Chrome | ❌ Announces value, but not related max | ✅ |
| Jaws (PC) + Edge | ❌ Announces value, but not related max | ✅ |
| Jaws (PC) + Firefox | ✅ | ✅ |
| NVDA (PC) + Chrome | ❌ Announces value, but not related max | ✅ |
| NVDA (PC) + Edge | ❌ Announces value, but not related max | ✅ |
| NVDA (PC) + Firefox | ✅ | ✅ |
| Narrator (PC) + Chrome | ✅ | ✅ |
| Narrator (PC) + Edge | ✅ | ✅ |
| Narrator (PC) + Firefox | ✅ | ✅ |
| TalkBack (Android) + Chrome | ❌ Announces value, but not related max | ✅ |
| TalkBack (Android) + Firefox | ❌ Announces value, but not related max | ✅ |
| TalkBack (Android) + Samsung Internet | ❌ Announces value, but not related max | ✅ |
Specifications
- DOM interface: HTMLProgressElement
- HTML Standard: The <progress> element
Changelog
- 1.1.1: Not writing redundant
aria-valuenow,aria-valueminandaria-valuemaxwhen iOS does not properly supportrole="progress" - 1.1.0: Framework compatibility:
- Setting
valueormaxproperties tonullorundefinedremoves the attribute, like frameworks expect for a native element (i.e.value={undefined}for indeterminate) - Better handling of
aria-labelledbyandaria-labelwritten by the consumer aria-labelledbytakes precedence overaria-label, then<label>, like the accessible name computationaria-labelledbyis replaced by a reference to the element itself instead of removed, so removing it later falls back toaria-labelor<label>- Label is re-synced after framework-rendering, as
<label for>oraria-labelledbyreferences may be available async (i.e. Angular and Qwik) idis observed, so a<label for>matching anidwritten after connect is found- Framework typings for Qwik 1, Qwik 2 and Preact 11 uses
HTMLElementTagNameMap
- Setting
- 1.0.1: Use
attachInternalswhen supported by the current browser and speed up attribute assignment - 1.0.0: Plays nice with strict CSP, and renders attributes in consistent order
- 0.0.7: Uses
role="progress"also in Firefox who now has sufficient support - 0.0.6: Enable declarative shadow root support and export
UHTMLProgressShadowRootfor easier server side rendering