Ein grundlegender Überblick darüber, wie du mit dem Element <progress>
eine adaptive und barrierefreie Ladeleiste erstellst.
In diesem Beitrag möchte ich darauf eingehen, wie Sie eine adaptive Farbe
zugängliche Ladeleiste mit dem Element <progress>
. Testen Sie
Demo-Video und sehen Sie sich die
Quelle.
Falls Sie Videos bevorzugen, finden Sie hier eine YouTube-Version dieses Beitrags:
Übersicht
Die
<progress>
gibt den Nutzenden visuelles und akustisches Feedback zum Abschluss. Dieses
visuelles Feedback ist hilfreich für Szenarien wie den Fortschritt eines Formulars,
um Informationen zum Herunterladen oder Hochladen anzuzeigen oder sogar zu zeigen,
Fortschrittsgrad ist unbekannt, aber Arbeit ist noch aktiv.
Bei dieser GUI Challenge wurde
das vorhandene HTML-<progress>
-Element verwenden, um die Barrierefreiheit zu verbessern. Die
Farben und Layouts die Grenzen der Anpassung für das integrierte Element aus,
die Komponente zu modernisieren und besser
in Designsysteme zu integrieren.
Markup
Ich habe mich entschieden, das <progress>
-Element mit einem
<label>
damit
Ich könnte die expliziten Beziehungsattribute zugunsten einer impliziten
Beziehung.
Ich habe auch ein übergeordnetes Element
beschriftet, das vom Ladestatus betroffen ist.
Lesetechnologien können diese Informationen
an die Nutzenden zurückgeben.
<progress></progress>
Ist kein value
vorhanden, beträgt der Fortschritt des Elements
unbestimmt.
Das Attribut max
ist standardmäßig auf 1 gesetzt, der Fortschritt liegt also zwischen 0 und 1. max
wird festgelegt
100 setzen, wird der Bereich auf 0 bis 100 gesetzt. Ich habe mich dafür entschieden, innerhalb der 0 zu bleiben.
und 1 Grenzwerte, wodurch die Fortschrittswerte
in 0,5 oder 50 % übersetzt werden.
Fortschritt bei Label-Wrapping
In einer impliziten Beziehung wird ein Fortschrittselement wie folgt von einem Label umschlossen:
<label>Loading progress<progress></progress></label>
In meiner Demo habe ich mich dafür entschieden, das Label für Screenreader
.
Dazu wird der Labeltext in einem <span>
umgebrochen und es werden Stile angewendet
zu verschieben, damit es sich außerhalb des Bildschirms befindet:
<label>
<span class="sr-only">Loading progress</span>
<progress></progress>
</label>
Mit folgendem CSS-Code von WebAIM:
.sr-only {
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
}
Vom Ladefortschritt betroffene Bereiche
Wenn du ein gesundes Sehvermögen hast, kann es leicht sein, eine Fortschrittsanzeige
mit verwandten Elementen und Seitenbereichen, aber für sehbehinderte Nutzende
so klar. Sie können dies verbessern, indem Sie die
aria-busy
-Attribut zum obersten Element hinzu, das sich ändert, wenn der Ladevorgang abgeschlossen ist.
Zeigen Sie außerdem eine Beziehung zwischen dem Fortschritt und der Ladezone an.
mit
aria-describedby
<main id="loading-zone" aria-busy="true">
…
<progress aria-describedby="loading-zone"></progress>
</main>
In JavaScript wechseln Sie zu Beginn der Aufgabe mit der Umschaltoption aria-busy
in true
und
false
:
Hinzufügungen von Aria-Attributen
Die implizite Rolle eines <progress>
-Elements ist
progressbar
, ich habe das explizit angegeben
für Browser ohne diese implizite Rolle. Ich habe auch das Attribut
indeterminate
, um das Element explizit in den Status „Unbekannt“ zu versetzen.
klarer ist, als das Element zu beobachten,
kein value
festgelegt ist.
<label>
Loading
<progress
indeterminate
role="progressbar"
aria-describedby="loading-zone"
tabindex="-1"
>unknown</progress>
</label>
Verwenden Sie
tabindex="-1"
damit das Fortschrittselement
von JavaScript aus fokussierbar ist. Das ist wichtig für
Screenreader-Technologie zu verwenden, da der Fortschritt
informiert den Nutzer darüber, wie weit der aktualisierte Fortschritt bereits erreicht ist.
Stile
Das Progress-Element ist etwas komplizierter. Integriertes HTML weisen besondere versteckte Teile auf, die schwer auszuwählen sind und nur eine begrenzte Anzahl von Properties zur Verfügung stellen.
Layout
Die Layout-Stile sollen eine gewisse Flexibilität bei der Entwicklung ermöglichen. der Größe und der Label-Position des Elements. Es wird ein spezieller Abschlussstatus hinzugefügt, der ein nützlicher, aber nicht unbedingt erforderlicher zusätzlicher visueller Hinweis.
<progress>
-Layout
Die Breite des Fortschrittselements bleibt unverändert, sodass es verkleinern und vergrößern kann.
mit dem benötigten Raum im Design. Die integrierten Stile sind
appearance
und border
werden auf none
festgelegt. So kann das Element
browserübergreifend normalisiert, da jeder Browser seine eigenen Stile
-Elements.
progress {
--_track-size: min(10px, 1ex);
--_radius: 1e3px;
/* reset */
appearance: none;
border: none;
position: relative;
height: var(--_track-size);
border-radius: var(--_radius);
overflow: hidden;
}
Der Wert von 1e3px
für _radius
verwendet eine wissenschaftliche Zahl
, um eine bestimmte
große Zahl, damit border-radius
immer gerundet wird. Entspricht
1000px
Ich verwende sie gerne, weil ich einen Wert
verwenden möchte, der groß genug ist,
Ich kann es festlegen und entkoppeln (und es ist kürzer als 1000px
). Es ist auch
bei Bedarf ganz einfach vergrößern: Ändern Sie einfach die 3 in eine 4, dann ist 1e4px
gleichbedeutend mit 10000px
.
„overflow: hidden
“ wurde in einem strittigen Stil verwendet. Das machte einige
So müssen Sie beispielsweise border-radius
-Werte nicht an den
Füllelemente verfolgen und verfolgen. aber auch den Fortschritt nicht nachzuahmen,
außerhalb des Elements leben. Eine weitere Iteration dieses benutzerdefinierten Fortschritts
kann ohne overflow: hidden
erstellt werden, wodurch einige
Animationen oder einen besseren Abschlussstatus zu erzielen.
Vorgang abgeschlossen
CSS-Selektoren erledigen hier die schwierige Arbeit, indem sie den Maximalwert mit dem Wert vergleichen. Wenn sie übereinstimmen, ist der Fortschritt abgeschlossen. Nach Abschluss wird ein Pseudoelement generiert und an das Ende des progress -Elements angehängt, das einen schönen zusätzlichen visuellen Hinweis auf den Abschluss bietet.
progress:not([max])[value="1"]::before,
progress[max="100"][value="100"]::before {
content: "✓";
position: absolute;
inset-block: 0;
inset-inline: auto 0;
display: flex;
align-items: center;
padding-inline-end: max(calc(var(--_track-size) / 4), 3px);
color: white;
font-size: calc(var(--_track-size) / 1.25);
}
Farbe
Der Browser verwendet eigene Farben für das Fortschrittselement und ist anpassungsfähig, „Hell“ und „Dunkel“ mit nur einer CSS-Eigenschaft. Dies kann mit einigen spezielle browserspezifische Selektoren.
Helle und dunkle Browserstile
So aktivierst du auf deiner Website ein adaptives <progress>
-Element mit dunklem und hellem Design:
Sie brauchen nur color-scheme
.
progress {
color-scheme: light dark;
}
Füllfarbe des Fortschritts einer einzelnen Unterkunft
Verwende accent-color
, um ein <progress>
-Element zu färben.
progress {
accent-color: rebeccapurple;
}
Beachten Sie, dass sich die Hintergrundfarbe der Spur von hell zu dunkel wechselt, je nachdem,
accent-color
Der Browser sorgt für einen angemessenen Kontrast: ziemlich übersichtlich.
Vollständig benutzerdefinierte helle und dunkle Farben
Legen Sie zwei benutzerdefinierte Eigenschaften für das <progress>
-Element fest, eine für die Track-Farbe.
und die andere für die Farbe des Fortschritts. Im Inneren der
prefers-color-scheme
Medienabfrage eingeben, neue Farbwerte für den Titel angeben und den Fortschritt verfolgen.
progress {
--_track: hsl(228 100% 90%);
--_progress: hsl(228 100% 50%);
}
@media (prefers-color-scheme: dark) {
progress {
--_track: hsl(228 20% 30%);
--_progress: hsl(228 100% 75%);
}
}
Fokusstile
Wir haben dem Element bereits einen negativen Tabindex zugewiesen, damit es programmatisch
fokussiert sind. Verwenden Sie
:focus-visible
bis
Passe den Fokus an, um den intelligenten Fokusring zu aktivieren. Dabei wird eine Maus
wird der Fokus nicht angezeigt, Klicks über die Tastatur jedoch schon. Die
In YouTube-Videos wird dies ausführlicher beschrieben.
eine Überprüfung lohnen.
progress:focus-visible {
outline-color: var(--_progress);
outline-offset: 5px;
}
Benutzerdefinierte Stile für verschiedene Browser
Passen Sie die Stile an, indem Sie die Teile eines <progress>
-Elements auswählen, die jeweils
die der Browser freigibt. Das progress -Element wird als einzelnes Tag verwendet,
Einige untergeordnete Elemente, die über CSS-Pseudoselektoren bereitgestellt werden. Chrome-Entwicklertools
werden folgende Elemente angezeigt, wenn Sie die Einstellung aktivieren:
- Klicke mit der rechten Maustaste auf deine Seite und wähle Inspect Element aus, um die Entwicklertools aufzurufen.
- Klicken Sie oben rechts im Entwicklertools-Fenster auf das Zahnradsymbol für die Einstellungen.
- Aktivieren Sie unter der Überschrift Elements die Option Elements. DOM.
Safari- und Chromium-Stile
WebKit-basierte Browser wie Safari und Chromium veröffentlichen
::-webkit-progress-bar
und ::-webkit-progress-value
, die eine Teilmenge von
Zu verwendendes CSS. Legen Sie background-color
vorerst mithilfe der benutzerdefinierten Eigenschaften fest
die sich an Helligkeit und Dunkelheit anpassen.
/* Safari/Chromium */
progress[value]::-webkit-progress-bar {
background-color: var(--_track);
}
progress[value]::-webkit-progress-value {
background-color: var(--_progress);
}
Firefox-Stile
Firefox zeigt nur den Pseudoselektor ::-moz-progress-bar
auf der
<progress>
-Element. Das bedeutet auch, dass wir den Titel nicht direkt färben können.
/* Firefox */
progress[value]::-moz-progress-bar {
background-color: var(--_progress);
}
Beachten Sie, dass in Firefox in Safari für iOS die Track-Farbe auf accent-color
eingestellt ist.
eine hellblaue Spur. Das Gleiche gilt im dunklen Modus: Firefox hat eine dunkle Spur,
und nicht die von uns festgelegte benutzerdefinierte Farbe. Sie funktioniert in WebKit-basierten Browsern.
Animation
Bei der Arbeit mit im Browser integrierten Pseudoselektoren ist dies häufig mit der zulässigen CSS-Eigenschaften.
Animation der Strecke, die sich füllt
Durch Hinzufügen eines Übergangs zum
inline-size
von
Das progress-Element funktioniert für Chromium, aber nicht für Safari. Firefox kann auch
kein Übergangsattribut für ::-moz-progress-bar
.
/* Chromium Only 😢 */
progress[value]::-webkit-progress-value {
background-color: var(--_progress);
transition: inline-size .25s ease-out;
}
Status :indeterminate
animieren
Hier werde ich etwas kreativer, damit ich eine Animation bereitstellen kann. Ein Pseudoelement für Chromium erstellt und ein Farbverlauf angewendet wird, für alle drei Browser.
Benutzerdefinierte Eigenschaften
Benutzerdefinierte Eigenschaften eignen sich
für viele Dinge, aber einer meiner Favoriten
einem ansonsten magisch aussehenden CSS-Wert
einen Namen geben. Es ist ziemlich einfach,
komplex
linear-gradient
,
aber mit einem hübschen Namen. Sein Zweck und seine Anwendungsfälle sind klar nachvollziehbar.
progress {
--_indeterminate-track: linear-gradient(to right,
var(--_track) 45%,
var(--_progress) 0%,
var(--_progress) 55%,
var(--_track) 0%
);
--_indeterminate-track-size: 225% 100%;
--_indeterminate-track-animation: progress-loading 2s infinite ease;
}
Benutzerdefinierte Eigenschaften tragen auch dazu bei, dass der Code DRY bleibt, da wir wieder keine können Sie diese browserspezifischen Selektoren gruppieren.
Die Keyframes
Das Ziel ist eine unendliche Animation, die hin und her wechselt. Anfang und Ende
werden in CSS festgelegt. Es ist nur ein Keyframe erforderlich: der mittlere Keyframe.
um 50%
, um eine Animation zu erstellen,
immer wieder neu!
@keyframes progress-loading {
50% {
background-position: left;
}
}
Targeting auf jeden Browser
Nicht in jedem Browser können Pseudoelemente im <progress>
erstellt werden.
Element selbst oder ermöglicht das Animieren der Fortschrittsanzeige. Weitere Browserunterstützung
statt eines Pseudoelements. Daher führe ich ein Upgrade von Pseudoelementen als
als Basis und in Animationsbalken.
Chromium-Pseudoelement
Chromium lässt das Pseudoelement „::after
“ mit einer abzudeckenden Position zu.
das Element. Die unbestimmten benutzerdefinierten Eigenschaften werden verwendet,
der vierten Animation funktioniert.
progress:indeterminate::after {
content: "";
inset: 0;
position: absolute;
background: var(--_indeterminate-track);
background-size: var(--_indeterminate-track-size);
background-position: right;
animation: var(--_indeterminate-track-animation);
}
Safari-Fortschrittsanzeige
In Safari werden die benutzerdefinierten Eigenschaften und eine Animation auf das Fortschrittsanzeige für Pseudoelement:
progress:indeterminate::-webkit-progress-bar {
background: var(--_indeterminate-track);
background-size: var(--_indeterminate-track-size);
background-position: right;
animation: var(--_indeterminate-track-animation);
}
Firefox-Fortschrittsanzeige
In Firefox werden die benutzerdefinierten Eigenschaften und eine Animation auch auf das Fortschrittsanzeige für Pseudoelement:
progress:indeterminate::-moz-progress-bar {
background: var(--_indeterminate-track);
background-size: var(--_indeterminate-track-size);
background-position: right;
animation: var(--_indeterminate-track-animation);
}
JavaScript
JavaScript spielt beim <progress>
-Element eine wichtige Rolle. Sie steuert
Wert, der an das Element gesendet wird, und stellt sicher, dass genügend Informationen im
für Screenreader.
const state = {
val: null
}
Die Demo enthält Schaltflächen zur Steuerung des Fortschritts: sie/er aktualisiert state.val
und dann eine Funktion zum Aktualisieren der
DOM enthält.
document.querySelector('#complete').addEventListener('click', e => {
state.val = 1
setProgress()
})
setProgress()
In dieser Funktion findet die UI/UX-Orchestrierung statt. Erstellen Sie als Erstes ein
setProgress()
. Es sind keine Parameter erforderlich, da sie Zugriff auf die
state
-Objekt, Fortschrittselement und <main>
-Zone.
const setProgress = () => {
}
Ladestatus für die Zone <main>
festlegen
Je nachdem, ob der Fortschritt abgeschlossen ist oder nicht, werden die entsprechenden <main>
-Element erfordert ein Update des
aria-busy
Attribut:
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
}
Attribute löschen, wenn der Ladebetrag unbekannt ist
Wenn der Wert unbekannt oder nicht konfiguriert ist, null
bei dieser Verwendung, entfernen Sie value
und
aria-valuenow
-Attribute. Dadurch wird <progress>
in „Unbestimmt“ geändert.
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
}
Probleme mit Dezimalzahlen in JavaScript beheben
Da ich mich für den Standardwert von 1 für den Fortschritt entschieden habe,
Für Inkrement- und Dekrement-Funktionen werden Dezimalzahlen verwendet. JavaScript und andere
Sprachen nicht immer gut
.
Hier ist eine roundDecimals()
-Funktion, mit der überflüssige Berechnungen reduziert werden.
Ergebnis:
const roundDecimals = (val, places) =>
+(Math.round(val + "e+" + places) + "e-" + places)
Runden Sie den Wert, damit er angezeigt werden kann und lesbar ist:
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
const val = roundDecimals(state.val, 2)
const valPercent = val * 100 + "%"
}
Wert für Screenreader und Browserstatus festlegen
Der Wert wird an drei Stellen im DOM verwendet:
- Das
value
-Attribut des<progress>
-Elements. - Das Attribut
aria-valuenow
. - Der innere Textinhalt
<progress>
.
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
const val = roundDecimals(state.val, 2)
const valPercent = val * 100 + "%"
progress.value = val
progress.setAttribute('aria-valuenow', valPercent)
progress.innerText = valPercent
}
Den Fortschritt in den Fokus rücken
Wenn die Werte aktualisiert wurden, sehen sehende Nutzer zwar den Fortschritt,
Leser wurden noch nicht über die Änderung informiert. Fokus auf die
<progress>
-Element und der Browser kündigt das Update an.
const setProgress = () => {
zone.setAttribute('aria-busy', state.val < 1)
if (state.val === null) {
progress.removeAttribute('aria-valuenow')
progress.removeAttribute('value')
progress.focus()
return
}
const val = roundDecimals(state.val, 2)
const valPercent = val * 100 + "%"
progress.value = val
progress.setAttribute('aria-valuenow', valPercent)
progress.innerText = valPercent
progress.focus()
}
Fazit
Jetzt, wo du weißt, wie ich es gemacht habe, wie würdest du... ‽ 🙂
Es gibt sicherlich ein paar Änderungen, die ich gerne vornehmen würde, wenn ich noch eine Gelegenheit dazu hätte. Ich denke, es ist Raum, die aktuelle Komponente zu bereinigen, und Raum, eine ohne die Stilbeschränkungen der Pseudoklasse des <progress>
-Elements zu erstellen. Es lohnt sich!
Lassen Sie uns unsere Herangehensweisen diversifizieren und alle Möglichkeiten kennenlernen, wie wir das Web entwickeln können.
Erstelle eine Demo, twittere mir Links und ich füge sie hinzu im Abschnitt „Community-Remixe“ weiter unten.