Das HTML5-Fortschrittselement

Avatar of Pankaj Parashar
Pankaj Parashar am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Der folgende Text ist ein Gastbeitrag von Pankaj Parashar. Pankaj schrieb mir über einige ziemlich coole gestylte Fortschrittselemente, die er erstellt hatte. Ich fragte ihn, ob er daran interessiert sei, die Idee zu einem Artikel über das allgemeine Styling zu erweitern. Glücklicherweise willigte er mit diesem großartigen Artikel ein, der die Verwendung in HTML, das bestmögliche Styling mit CSS browserübergreifend und Fallbacks behandelt.

Hier ist die grundlegende Markierung für das Fortschrittselement

<progress></progress>

Gemäß dem Standard des W3C repräsentiert das Fortschrittselement den Abschlussfortschritt einer Aufgabe. Ein Fortschrittselement muss sowohl ein Start-Tag (d. h. <progress>) als auch ein End-Tag (d. h. </progress>) haben, auch wenn es wie ein ersetztes Element (wie ein Eingabefeld) aussieht. Das ist jedoch gut, da es beim Fallback-Inhalt hilft, wie wir später besprechen werden.

Zusätzlich zu den globalen Attributen kann es zwei weitere Attribute haben

  • max – Gibt an, wie viel Arbeit getan werden muss, bevor sie als abgeschlossen gilt. Wenn nicht angegeben, ist der Standardwert 1.0.
  • value – Zeigt den aktuellen Status des Fortschrittsbalkens an. Er muss größer oder gleich 0.0 und kleiner oder gleich 1.0 oder dem Wert des Attributs max (falls vorhanden) sein.

Zustände des Fortschrittsbalkens

Ein Fortschrittsbalken kann zwei Zustände haben – **unbestimmt** und **bestimmt**.

1. Unbestimmt

Unbestimmter Zustand des Fortschrittsbalkens in Chrome 29 auf Mac OS 10.8

Abhängig von Ihrer Kombination aus Browser und Betriebssystem kann der Fortschrittsbalken unterschiedlich aussehen. Zoltan „Du Lac“ Hawryluk behandelt das browserübergreifende Verhalten von Fortschrittselementen in ausführlicher Tiefe in seinem Artikel zu HTML5-Fortschrittsbalken (der definitiv lesenswert ist). Wufoo hat einige Screenshots, wie es auf anderen Betriebssystemen aussieht, auf ihrer Support-Seite für Fortschritt.

Es ist ziemlich einfach, einen unbestimmten Fortschrittsbalken anzusprechen und zu stylen, da wir wissen, dass er kein Attribut value enthält. Wir können die CSS-Negationsklausel :not() verwenden, um ihn zu stylen

progress:not([value]) {
   /* Styling here */
}

2. Bestimmt

In diesem Artikel konzentrieren wir uns nur auf das Styling des bestimmten Zustands des Fortschrittsbalkens. Ändern wir also den Zustand, indem wir die Attribute max und value hinzufügen.

<progress max="100" value="80"></progress>

Ohne jegliches CSS sieht der Fortschrittsbalken in Chrome 29 auf Mac OS 10.8 so aus.

Bestimmter Zustand des Fortschrittsbalkens in Chrome 29 auf Mac OS 10.8
Beachten Sie, dass das Hinzufügen des Attributs max allein den Zustand des Fortschrittsbalkens nicht ändert, da der Browser immer noch nicht weiß, welchen Wert er darstellen soll.

Das ist so ziemlich alles, was wir in HTML tun können, der Rest der Arbeit wird von CSS erledigt. Lassen Sie uns zu diesem Zeitpunkt nicht um Fallback-Techniken für die Unterstützung älterer Browser kümmern, die das Fortschrittselement nicht verstehen.

Styling von Fortschrittsbalken

Wir können bestimmte Fortschrittsbalken mit dem Selektor progress[value] ansprechen. Die Verwendung von nur progress ist in Ordnung, solange Sie wissen, dass Sie keine unbestimmten Fortschrittsbalken in Ihrer Markierung haben. Ich verwende eher ersteres, da es eine klare Unterscheidung zwischen den beiden Zuständen bietet. Genau wie bei jedem anderen Element können wir unserem Fortschrittsbalken Abmessungen mit width und height geben

progress[value] {
  width: 250px;
  height: 20px;
}

Hier endet der unterhaltsame Teil und die Dinge werden kompliziert, da jede Browserkategorie separate Pseudoklassen zum Stylen des Fortschrittsbalkens bereitstellt. Um die Dinge zu vereinfachen, kümmern wir uns nicht wirklich darum, welche Versionen jedes Browsers das Fortschrittselement unterstützen, da unsere Fallback-Technik sich um den Rest kümmert. Wir klassifizieren sie wie folgt

  • WebKit/Blink-Browser
  • Firefox
  • Internet Explorer

WebKit/Blink (Chrome/Safari/Opera)

Google Chrome, Apple Safari und die neueste Version von Opera (16+) fallen in diese Kategorie. Es ist aus dem User-Agent-Stylesheet von Webkit-Browsern ersichtlich, dass sie sich auf -webkit-appearance: progress-bar verlassen, um das Aussehen des Fortschrittselements zu stylen.

User-Agent-Stylesheet von Webkit-Browsern

Um die Standardstile zurückzusetzen, setzen wir einfach -webkit-appearance auf none.

progress[value] {
  /* Reset the default appearance */
  -webkit-appearance: none;
   appearance: none;

  width: 250px;
  height: 20px;
}
Fortschrittsbalken-Aussehen nach dem Zurücksetzen

Bei weiterer Inspektion des Fortschrittselements in Chrome Entwicklertools können wir sehen, wie der Standard umgesetzt wird.

Chrome Entwicklertools Snapshot

WebKit/Blink bietet zwei Pseudoklassen zum Stylen des Fortschrittselements

  • -webkit-progress-bar ist die Pseudoklasse, die zum Stylen des Containers des Fortschrittselements verwendet werden kann. In dieser Demo ändern wir die Hintergrundfarbe, die abgerundeten Ecken und wenden dann einen Innen-Schatten auf den Container des Fortschrittselements an.
  • -webkit-progress-value ist die Pseudoklasse zum Stylen des Werts innerhalb des Fortschrittsbalkens. Die background-color dieses Elements ist standardmäßig grün, was durch Inspektion des User-Agent-Stylesheets überprüft werden kann. Für diese Demo erstellen wir einen Bonbonstreifen-Effekt mit einem linearen Gradienten für die background-image-Eigenschaft.

Zuerst stylen wir -webkit-progress-bar (den Container)

progress[value]::-webkit-progress-bar {
  background-color: #eee;
  border-radius: 2px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;
}
Styling des Fortschrittsbalken-Containers

Als nächstes stylen wir -webkit-progress-value (den Balken) mit mehreren Gradientenhintergründen. Einer für Streifen, einer für Schatten von oben nach unten und einer für Farbvariationen von links nach rechts. Wir verwenden das -webkit-Präfix für die Gradienten, da wir es ohnehin für den Fortschrittsbalken selbst verwenden.

progress[value]::-webkit-progress-value {
  background-image:
	   -webkit-linear-gradient(-45deg, 
	                           transparent 33%, rgba(0, 0, 0, .1) 33%, 
	                           rgba(0,0, 0, .1) 66%, transparent 66%),
	   -webkit-linear-gradient(top, 
	                           rgba(255, 255, 255, .25), 
	                           rgba(0, 0, 0, .25)),
	   -webkit-linear-gradient(left, #09c, #f44);

    border-radius: 2px; 
    background-size: 35px 20px, 100% 100%, 100% 100%;
}
Styling des Fortschrittsbalken-Werts

Hinzufügen von Animationen

Zum Zeitpunkt des Schreibens unterstützen nur WebKit/Blink-Browser Animationen für das Fortschrittselement. Wir animieren die Streifen auf -webkit-progress-value, indem wir die Hintergrundposition ändern.

@-webkit-keyframes animate-stripes {
   100% { background-position: -100px 0px; }
}

@keyframes animate-stripes {
   100% { background-position: -100px 0px; }
}

Und verwenden diese Animation auf dem -webkit-progress-value-Selektor selbst.

-webkit-animation: animate-stripes 5s linear infinite;
        animation: animate-stripes 5s linear infinite;

Update: Animationen scheinen auf den Pseudoelementen innerhalb eines Fortschrittselements in Blink nicht mehr zu funktionieren. Zum Zeitpunkt der Veröffentlichung funktionierten sie. Brian LePore hat mich darauf aufmerksam gemacht und mich auf diesen Thread verwiesen, der dies diskutiert, und einen reduzierten Testfall erstellt. Simuaris Gedanke

Vielleicht ist es dasselbe mit dem <progress>, dass außerhalb des Shadow DOM definierte @keyframes nicht von einem Element im Inneren abgerufen werden können. Vom Timing her könnte sich das in Chromium 39/40 geändert haben?

und auch

Was zu funktionieren scheint, ist das Verschieben der Animation von progress::-webkit-progress-bar zu progress

Bardi Harborow berichtet, dass dies nicht stimmt, und weist auch auf den protokollierten Fehler hin.

Pseudoelemente

Zum Zeitpunkt des Schreibens unterstützen nur WebKit/Blink-Browser die Pseudoelemente ::before und ::after auf dem Fortschrittsbalken. Allein durch Betrachten des Fortschrittsbalkens ist der tatsächliche Wert nicht ersichtlich. Wir können dieses Problem lösen, indem wir den tatsächlichen Wert am Ende des Fortschrittsbalkens mit entweder ::before oder ::after anzeigen.

progress[value]::-webkit-progress-value::before {
  content: '80%';
  position: absolute;
  right: 0;
  top: -125%;
}
Pseudoelemente in Aktion

Interessanterweise funktioniert content: attr(value) bei Fortschrittsbalken nicht. Wenn Sie jedoch den Text explizit im Content-Attribut angeben, funktioniert es! Ich konnte den Grund für dieses Verhalten nicht herausfinden. Da dies nur in WebKit/Blink-Browsern funktioniert, gibt es keinen guten Grund, Inhalte in Pseudoelementen einzubetten, zumindest vorerst.

Update 11/2016: progress::after { content: attr(value); } scheint jetzt in Blink zu funktionieren, aber sonst nichts.

Ebenso wird ::after verwendet, um einen schönen kleinen Scharnier-Effekt am Ende des Fortschrittsbalkens zu erzeugen. Diese Techniken sind experimentell und werden nicht wirklich empfohlen, wenn Sie auf browserübergreifende Konsistenz abzielen.

progress[value]::-webkit-progress-value::after {
  content: '';
  width: 6px;
  height: 6px;
  position: absolute;
  border-radius: 100%;
  right: 7px;
  top: 7px;
  background-color: white;
}

2. Firefox

Ähnlich wie WebKit/Blink verwendet Firefox -moz-appearance: progressbar, um das Fortschrittselement zu rendern.

Firebug-Screenshot

Durch die Verwendung von appearance: none können wir die standardmäßige Facetten- und Prägungsoptik entfernen. Dies hinterlässt leider einen schwachen Rand in Firefox, der durch border: none entfernt werden kann. Dies löst auch das Randproblem mit Opera 12.

progress[value] {
  /* Reset the default appearance */
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  
  /* Get rid of default border in Firefox. */
  border: none;
  
  /* Dimensions */
  width: 250px;
  height: 20px;
}
Schwacher Rand in Firefox und Opera

Firefox bietet eine einzige Pseudoklasse (-moz-progress-bar), die wir zum Ansprechen des Fortschrittsbalken-Werts verwenden können. Das bedeutet, dass wir den Hintergrund des Containers in Firefox nicht stylen können.

progress[value]::-moz-progress-bar { 
  background-image:
    -moz-linear-gradient(
      135deg, 
      transparent 33%, 
      rgba(0, 0, 0, 0.1) 33%, 
      rgba(0, 0, 0, 0.1) 66%, 
      transparent 66% 
    ),
    -moz-linear-gradient(
      top, 
      rgba(255, 255, 255, 0.25), 
      rgba(0, 0, 0, 0.25)
    ),
    -moz-linear-gradient(
      left, 
      #09c, 
      #f44
    );

  border-radius: 2px; 
  background-size: 35px 20px, 100% 100%, 100% 100%; 
}

Firefox unterstützt keine ::before- oder ::after-Pseudoklassen für Fortschrittsbalken und erlaubt auch keine CSS3 Keyframe Animation für Fortschrittsbalken, was uns eine etwas eingeschränkte Erfahrung bietet.

3. Internet Explorer

Nur IE 10+ unterstützt Fortschrittsbalken nativ und nur teilweise. Er erlaubt nur die Änderung der Farbe des Fortschrittsbalken-Werts. IE implementiert den Wert des Fortschrittsbalkens als Attribut color anstelle von background-color.

progress[value]  {
  /* Reset the default appearance */
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;

  /* Get rid of default border in Firefox. */
  border: none;

  /* Dimensions */
  width: 250px;
  height: 20px;

  /* For IE10 */
  color: blue; 
}

Was ist mit Browsern, die sie nicht unterstützen?

Das Fortschrittselement wird nativ unterstützt in: Firefox 16+, Opera 11+, Chrome, Safari 6+. IE10+ unterstützt sie teilweise. Wenn Sie ältere Browser unterstützen möchten, haben Sie zwei Möglichkeiten.

1. Lea Verous HTML5-Fortschritts-Polyfill

Lea Verous exzellentes Polyfill bietet nahezu vollständige Unterstützung für Firefox 3.5-5, Opera 10.5-10.63, IE9-10. Dies bietet auch teilweise Unterstützung für IE8. Dazu gehört das Einbinden der Datei progress-polyfill.js in Ihr HTML und das Hinzufügen von CSS-Selektoren, die die Skriptdatei verwendet. Um mehr über die Verwendung zu erfahren, schauen Sie sich den CSS-Quellcode der Projektseite an.

2. HTML-Fallback

Das ist mein bevorzugter Ansatz (ohne JavaScript). Er nutzt eine gängige Technik, die auch für die Elemente audio und video verwendet wird.

<progress max="100" value="80">
    <div class="progress-bar">
        <span style="width: 80%;">Progress: 80%</span>
    </div>
</progress>

Simulieren Sie das Aussehen und Gefühl eines Fortschrittsbalkens mit div und span innerhalb des Fortschritts-Tags. Moderne Browser ignorieren den Inhalt innerhalb des Fortschritts-Tags. Ältere Browser, die das Fortschrittselement nicht erkennen, ignorieren den Tag und rendern die darin enthaltene Markierung.

.progress-bar {
  background-color: whiteSmoke;
  border-radius: 2px;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.25) inset;

  width: 250px;
  height: 20px;
  
  position: relative;
  display: block;
}
  
.progress-bar > span {
  background-color: blue;
  border-radius: 2px;

  display: block;
  text-indent: -9999px;
}

Es ist üblich, beide Techniken zu kombinieren, und sie sind für Produktionsseiten absolut sicher. Sobald Sie das Styling eines einzelnen Fortschrittsbalkens beherrschen, ist das Hinzufügen von Stilen für mehrere Fortschrittsbalken lediglich eine Übung, die mit Klassen erreicht werden kann.

Siehe den Pen Skillset mit HTML5-Fortschrittsbalken mit CSS3-Animationen von CSS-Tricks (@css-tricks) auf CodePen.

Die Demo sollte in allen Browsern, einschließlich Internet Explorer (bis IE 8), einwandfrei laufen. Der Fortschrittsbalken ist in allen Versionen von Internet Explorer blau. Opera 11 und 12 erlauben keine Änderung der Fortschrittsbalkenfarbe. Daher wird die Standardfarbe Grün angezeigt. Die Demo verwendet zusätzliche Markierungen, um einige Meta-Informationen über den Fortschrittsbalken und den Prozentwert anzuzeigen.

Für zusätzliche Lektüre lesen Sie den Artikel von HTML5 Doctor. Er behandelt einige ähnliche Themen, enthält aber auch einige Informationen zu zusätzlichen Attributen und wie man den Balken mit JavaScript aktualisiert, falls Sie dies benötigen.