Das <progress>-Element ist die semantische Möglichkeit, den Fortschritt einer Aufgabe darzustellen, z. B. das Herunter- oder Hochladen von Informationen oder das Abschließen eines Teils eines mehrstufigen Prozesses. Die Verwendung des nativen Elements verbessert die Barrierefreiheit, da Screenreader eine implizite role="progressbar" haben und Werte ansagen können.
In diesem Leitfaden wird eine vollständig gestaltete horizontale Fortschrittsanzeige mit Stilanpassungen implementiert.
Fortschrittsanzeige oder Fortschritts-Ring?
- Wenn der Platz begrenzt ist oder ein quadratisches Seitenverhältnis bevorzugt wird, können Sie eine kreisförmige Fortschrittsanzeige (Fortschritts-Ring) verwenden: Fortschritts-Ring
- Für die meisten Szenarien mit unbestimmtem Fortschritt sind rotierende Ladesymbole (Rotierendes Ladesymbol) am besten geeignet. Verwenden Sie unbestimmte Fortschrittsanzeigen, wenn der unbestimmte Status vorübergehend ist und bald durch eine bestimmte Fortschrittsanzeige ersetzt wird (z. B. beim Warten auf Metadaten zu einem Upload, bevor ein Fortschritt in Prozent angezeigt werden kann).
Markieren & Zeichnen
- Natives
<progress>-Element verwenden: Es bietet integrierte Bedienungshilfen und ein plattformübergreifend einheitliches Verhalten. - Verwenden Sie
max, wenn eine andere Skala als die Standardskala von 0 bis 1 erforderlich ist. - Legen Sie für einen bestimmten Fortschrittswert ein
value-Attribut fest. Lassen Sievaluefür einen unbestimmten Status weg (z.B. bevor konkreteres Feedback beginnt). - Verwenden Sie
<label for="...">,aria-labelledbyoderaria-label, um das Fortschrittselement mit einem Label zu verknüpfen.
Welche Art von Anpassung ist erforderlich?
Für ein eingeschränktes Styling reichen diese Eigenschaften aus:
accent-color, um die Farbe der Fortschrittsanzeige zu ändernwidth/inline-size, um die Breite der Fortschrittsanzeige zu ändernheight/block-sizewird inkonsistent angewendet – zuerst testenwriting-mode: vertical-lrfür vertikale Balken.- Effekte, die nach dem Zeichnen angewendet werden:
opacity,filter,clip-path, Masken, Transformationen,box-shadowusw.
Wenn ein eingeschränktes Styling ausreicht, überspringen Sie den nächsten Abschnitt.
WARNUNG: Bestimmte Attribute (z.B. border-radius, background, border) deaktivieren automatisch den Standardstil der Fortschrittsanzeige. Wenn Sie über die oben genannten Eigenschaften hinausgehende Stile benötigen, müssen Sie vollständig benutzerdefinierte Stile implementieren, wie im nächsten Abschnitt beschrieben. Wenden Sie KEINE umfangreicheren Stile an, „nur für den Fall, dass es funktioniert“.
Vollständig benutzerdefinierte Stile
1. Grundlegende Einrichtung
- OBLIGATORISCH: Verwenden Sie
appearance: none, um benutzerdefinierte Stile zu aktivieren. - UA-Grenzen mit
border: 0 solidzurücksetzen - Wenn Sie die aktive Leiste auf den Rahmenradius des Elements beschneiden möchten, verwenden Sie
overflow: clipODER wenden Sie denselbenborder-radiusauf die Leiste an. Verwenden Sie NICHTborder-radius: inheritfür die Leiste, da dies von der spezifischen Struktur der Elemente im Shadow-DOM abhängt.
progress {
/* Reset default browser styles */
appearance: none;
border: 0 solid;
/* Clip bar to element’s border-radius */
overflow: clip;
}
2. Stile
- Gestalten Sie die Spur im
progress-Element selbst. - Verwenden Sie das entsprechende browserspezifische Pseudoelement, um die Fortschrittsanzeige selbst anzusprechen:
::-webkit-progress-valuefür WebKit/Blink und::-moz-progress-barfür Firefox. - OBLIGATORISCH: Gruppieren Sie die Pseudoelemente
-webkit-und-moz-NICHT in derselben Regel. Die Regel wird als ungültig eingestuft und ignoriert.:is()und:where()helfen hier nicht, da sie keine Pseudoelemente unterstützen. - Jedes auf den Browser ausgerichtete Pseudoelement sollte genau einmal vorkommen. Statusspezifische Anpassungen (z. B. die unbestimmte Segmentgröße und Animation) sollten über benutzerdefinierte Eigenschaften weitergeleitet werden, die für das
progress-Element selbst festgelegt sind. - Optional: Übergang
inline-sizefür die Füllung, damit sich Änderungen des bestimmten Werts animieren lassen, anstatt zu springen. Firefox passt die Größe des Füllbereichs im Layout an und ignoriert ihn, was unbedenklich ist.
progress {
--progress-bar-radius: 1e5px;
border-radius: var(--progress-bar-radius);
/* Apply color for custom progress track (background) */
background: var(--progress-bar-track, var(--color-neutral-90));
/* Subtle depth on the empty part of the track */
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);
}
/* Let <progress> styling show through */
progress::-webkit-progress-bar {
background: transparent;
}
/* Webkit, Chrome */
progress::-webkit-progress-value {
background: var(--progress-bar-fill, var(--accent-color));
border-radius: var(--progress-bar-radius);
transition: inline-size 0.3s;
}
/* Firefox */
progress::-moz-progress-bar {
background: var(--progress-bar-fill, var(--accent-color));
border-radius: var(--progress-bar-radius);
transition: inline-size 0.3s;
}
3. Stil für unbestimmten Status
Benutzerdefinierte Animation für den unbestimmten Status hinzufügen: Wandeln Sie das Pseudoelement für die Füllung in ein kurzes Segment um und lassen Sie es entlang der Spur gleiten.
- Gestalten Sie die Füllung selbst. Erstellen Sie sie NICHT als Hintergrund auf
progressneu. - Die unbestimmte Füllung existiert nur durch ihre Animation: Die Keyframes legen ihre Länge mit einem echten
inline-sizefest (dies schlägt das Inline-inline-sizedes Chromium-UA) und bewegen sie mittranslate. Verwenden Sie für die Länge NICHTscale, da dadurch alle Muster verzerrt werden, die auf die Füllung gezeichnet werden. translate-Prozentwerte werden anhand der Breite des Füllbereichs aufgelöst. Drücken Sie Positionen stattdessen in Track-Einheiten aus: Machen Sieprogresszu einem Container mit Inline-Größe und verwenden Siecqiin den Keyframes. Fügen Siemargin-right: autoinfrom, toein, damit Chromium die Füllung auch bei RTL-Sprachen auf der physischen linken Seite anzeigt.- Verwenden Sie Transformationen, nicht Ränder, um die Füllung zu verschieben.
- Transformationen behalten die Animation im Compositor bei (es sei denn,
inline-sizewird ebenfalls animiert) - Ränder werden in RTL aus zwei verschiedenen Gründen nicht richtig dargestellt:
- Firefox positioniert die unbestimmte Füllung nur anhand des physischen linken Rands.
margin-inline-starthat also keine Auswirkungen auf RTL und die Füllung wird nie verschoben. - In Chromium und WebKit, die die Füllung als normalen Block darstellen, addieren sich die Ränder zu mehr als der Spur, sobald ein Rand die Füllung über das Ende der Spur hinaus verschiebt. Im Standard-CSS wird dieses Problem gelöst, indem
margin-leftin RTL-Sprachen ignoriert wird. Das Segment springt dann an den Rand, anstatt darüber hinaus zu gleiten. translatewird nach dem Layout angewendet, sodass keines der Probleme auftritt.
- Transformationen behalten die Animation im Compositor bei (es sei denn,
- Wenn Sie die Bewegung in Sprachen mit Schreibrichtung von rechts nach links spiegeln möchten (wie es in der nativen Leiste von Chrome der Fall ist), kehren Sie die Animation unter
:dir(rtl)um:
progress:dir(rtl) {
--progress-bar-indeterminate-animation: progress-bar-indeterminate var(--progress-bar-indeterminate-animation-duration) infinite linear reverse;
}
- Definieren Sie die öffentlichen
--progress-bar-indeterminate-*-Eigenschaften fürprogress(ihr Name beschränkt sie bereits auf den Status), damit Nutzer sie überschreiben können, ohne:indeterminatezu kennen. - Wenn Sie die Segmentlänge variieren möchten (z. B. die Vorderkante bewegt sich schneller und die Hinterkante holt auf), legen Sie für
--progress-bar-indeterminate-animationzwei gleichzeitige Animationen fest: eine, deren Keyframestranslateincqi(Position) animieren, und eine, deren Keyframesinline-size(Länge) animieren. So erhält jede Animation eigene Keyframes und ein eigenes Easing. Versuchen Sie NICHT, beide Kanten in einer einzigen Keyframe-Liste zu formen. Der Keyframe-spezifischeanimation-timing-functiongilt für jede Property in diesem Keyframe. --progress-bar-animationgilt für beide Zustände und kann für Effekte wie ein bestimmtes Schimmern verwendet werden.revert-rulewird nur überschrieben, wenn es festgelegt ist, um die Kombinierbarkeit zu maximieren.- Deaktivieren Sie niemals die unbestimmte Animation (
animation: nonehinterlässt in Chromium eine Füllung mit einer Breite von null). Wenn du die Bewegung reduzieren möchtest, verlangsame sie stattdessen.
progress {
/* Lets the fill position itself in track units (cqi) */
container-type: inline-size;
/* Segment length relative to the track */
--progress-bar-indeterminate-size: 30%;
--progress-bar-indeterminate-animation-duration: 1.5s;
/* Respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
--progress-bar-indeterminate-animation-duration: 10s;
}
}
progress:indeterminate {
--progress-bar-animation: var(
--progress-bar-indeterminate-animation,
progress-bar-indeterminate var(--progress-bar-indeterminate-animation-duration) infinite linear
);
}
/* Add to the existing pseudo-element rules */
progress::-webkit-progress-value {
animation: var(--progress-bar-animation, revert-rule);
}
progress::-moz-progress-bar {
animation: var(--progress-bar-animation, revert-rule);
}
/* Physical: left to right regardless of direction (reverse under :dir(rtl) to mirror). */
@keyframes progress-bar-indeterminate {
from, to {
inline-size: var(--progress-bar-indeterminate-size);
/* Pin to the physical left; Chromium would otherwise lay the fill out at the inline start */
margin-right: auto;
}
from { translate: -100%; } /* Own width: fully outside the left edge */
to { translate: 100cqi; } /* Track width: fully outside the right edge */
}
Weitere Überlegungen zur Barrierefreiheit im Internet
Zusätzlich zu den oben genannten Richtlinien gilt Folgendes:
- Abschluss ankündigen, ohne den Fokus zu stehlen: Legen Sie
tabindexnicht fest und rufen Sie.focus()nicht für<progress>auf, da es nicht interaktiv ist und das Verschieben des Fokus auf dieses Element Tastaturnutzer stört. Wenn Sie ankündigen möchten, dass eine Hintergrundaufgabe abgeschlossen ist, aktualisieren Sie ein höfliches Statuselement (role="status"oderaria-live="polite"). - Fügen Sie keinen Fallback-Text in
<progress>ein: Text in<progress>wird von modernen Browsern ignoriert und nicht von Hilfstechnologien verwendet. - Vermeiden Sie
aria-busy+aria-describedbyfür ein nicht gekennzeichnetes generisches<div>.aria-busywird von Screenreadern nicht einheitlich unterstützt undaria-describedbyfür ein unbenanntes<div>ohne Rolle wird von Hilfstechnologien ignoriert. Wenn der Inhalt einer Region beim Laden nicht bereit ist, blenden Sie ihn mithiddenoderaria-hidden="true"aus. - EMPFOHLEN: Achten Sie beim Hinzufügen benutzerdefinierter Stile auf einen ausreichenden Kontrast zwischen der Fortschrittsanzeige und der Spur.
- Alternativen für die Darstellung eines unbestimmten Status in Betracht ziehen: Animationen für unbestimmte Fortschrittsanzeigen, die parallel zu anderen Inhalten angezeigt werden, können von einigen Nutzern als störend empfunden werden.
Fallback-Strategien
Fallbacks und Browserunterstützung für „accent-color“
Das Attribut accent-color ist eine progressive Verbesserung.
Browser, die diese Eigenschaft nicht unterstützen, ignorieren sie und verwenden ihre Standard-UI-Farben.
Wenn accent-color nicht unterstützt wird und die Fortschrittsanzeige angepasst werden muss, verwenden Sie die Methode für benutzerdefinierte Stile, um den gewünschten Stil auf die Fortschrittsanzeige anzuwenden.
Fallbacks und Browserunterstützung für revert-rule
Wenn revert-rule nicht unterstützt wird, greift animation: var(--progress-bar-animation, revert-rule) auf animation-name: revert-rule mit einer Dauer von 0s zurück, wenn --progress-bar-animation nicht festgelegt ist. Das ist ein harmloser No-Op, wenn kein @keyframes revert-rule vorhanden ist.