Ordnung ist das halbe Leben…

06. Juli 2011

Ordnung ist das halbe Leben
Geschachtelte geordnete Listen mit einer fortlaufenden Nummerierung in Form von 1., 1.1, 1.1.1 usw.? Seit CSS 2 lassen sich dank der neuen CSS-Counter auch solche Arten der Aufzählung realisieren. Für ältere Browser wie dem Internet Explorer 7 müssen dabei allerdings ein paar Hürden genommen werden. Dabei sind die CSS-Counter nicht auf Listenelemente beschränkt, da gäbe es eine ganze Reihe schöner Einsatzszenarien. Wahrlich kein brandneues Thema mehr, aber ein Blick lohnt trotzdem.

Geordnete Listen

CSS-Counter erlauben das Zählen von Instanzen bestimmter Elemente bzw. Selektoren. In Kombination mit den Pseudo-Elementen :before und :after lassen sich dann ganze neue Formen der Nummerierung erstellen. Die CSS-Counter sind dabei deutlich leistungsstärker als das alte HTML start Attribut, das ohnehin als deprecated gilt, und ausschließlich die Nummerierung einer Ebene bzw. eines Listenelementes beeinflusst.
Die Nummerierung mit Hilfe von CSS basiert setzt sich aus mehreren Eigenschaften und Funktionen zusammen:

  • counter-reset: Setzt einen oder mehrere Zähler zurück, ein Zähler ist dabei eine frei wählbare Variable. Optional lässt sich für jeden Zähler noch ein Anfangswert festlegen, der Standardwert ist 1.
  • counter-increment: Zählt einen oder mehrere Zähler hoch, auch hier kann man über einen zweiten optionalen integeren Wert die Zählweise beeinflussen (selbst negative Werte sind erlaubt).
  • content: Gibt mit Hilfe der Funktionen counter() oder counters() die Nummerierung aus.

Ein Beispiel

OL {
  counter-reset: item;
}
OL LI {
  display: block;
}
 
OL LI:before {
  content: counter(item) ". ";
  counter-increment: item;
}

Betrachtet man dieses erste Beispiel im Browser, so sieht das Ergebnis noch nicht anders aus, als eine ganz normale geordnete Liste (OL), der einzige Vorteil liegt darin, dass sich die Nummerierung nun erheblich besser gestalten lässt, ohne dass man weitere Tag Verschachtelungen vornehmen muss. Auf einen Nachteil sei an dieser Stelle auch gleich hingewiesen. In Sachen “Accessability” sind diese Lösungen negativ zu bewerten, denn über CSS generierter Content manipuliert die DOM nicht (siehe hier), so dass aktuelle Screen-Reader diese Informationen schlicht nicht ausgeben, die Liste hätte also keine Nummerierung mehr.
Für eine fortlaufende Nummerierung, die die übergeordneten Nummern übernimmt, kann man den CSS Code wie folgt verändern:

OL {
  counter-reset: item;
}
OL LI {
  display: block;
}
 
OL LI:before {
  content: counters(item, ".") ".";
  counter-increment: item;
}

Nun werden die Nummern der übergeordneten Listenelemente übernommen. Die Funktion counters() liefert im Gegensatz zu counter alle Instanzen eines Zählers gleichzeitig. Der zweite Parameter ist das Trennzeichen, mit dem diese Instanzen verkettet werden. Doch Vorsicht mit dieser Syntax. Sie führt im Internet Explorer 7 dazu, dass alle folgenden CSS Notationen nicht mehr interpretiert werden, selbst wenn diese in separaten Stylesheet Dateien abgelegt sind. Anscheinend bringt die Notation der Anfürhrungszeichen innerhalb der Klammern den CSS Interpreter völlig durcheinander. Bedeutet, man kann wahlweise sicher stellen, dass der entsprechende Code projektweit wirklich immer an letzter Stelle kommt, oder man nutzt die Funktion counter anstatt counters – wobei diese Lösung den CSS-Code abhängig von der möglichen Verschachtelungstiefe deutlich vergrößern kann:

/* 1. Ebene */
BODY OL {
  counter-reset: level1;
  list-style-type: none;
}
 
OL LI:before {
  content: counter(level1) ". ";
  counter-increment: level1;
}
 
/* 2. Ebene */
OL LI OL {
  counter-reset: level2;
}
 
OL LI OL LI:before {
  content: counter(level1) "." counter(level2) " ";
  counter-increment: level2;
}
 
/* 3. Ebene */
OL LI OL LI OL {
  counter-reset: level3;
}
 
OL LI OL LI OL LI:before {
  content: counter(level1) "." counter(level2) "." counter(level3) " ";
  counter-increment: level3;
}
...

Jetzt wird Maß genommen

21. Januar 2011

Jetzt wird Maß genommen
Mit HTML5 kommen viele neue Auszeichnungsmöglichkeiten. Dazu gehören bspw. die Elemente progress und meter. Die Auszeichnungen haben das Ziel, die Information “sinnvoller”, auszuzeichnen als vorher. Progress – Klassisch der Fortschrittsbalken, Meter für Verhältnisangaben. Was kann man mit diesen neuen Auszeichnungen heute schon anstellen?

Das Meter Element

Meter ist ein Inline-Element. Er dient der “Darstellung von Größen und Mengenverhältnissen innerhalb eines definierbaren Bereichs. In der Spezfikation heißt es:

The meter element represents a scalar measurement within a known range, or a fractional value; for example disk usage, the relevance of a query result, or the fraction of a voting population to have selected a particular candidate. [...] The meter element also does not represent a scalar value of arbitrary range — for example, it would be wrong to use this to report a weight, or height, unless there is a known maximum value.

Solche Verhältnisangaben werden im Normalfall aber nicht nur textuell gemacht, sie werden durch eine grafische Information ergänzt. Die Darstellung entspricht im Prinzip der eines Fortschrittbalkens, aber er dient eben nicht der Statusanzeige einer Aufgabe sondern der Darstellung von Mengen.Das Meter Element kennt sechs Attribute, alle Werte (wenn gesetzt) müssen valide Ganz- oder Fließkomma Zahlen sein.

  • Value: Ist schlicht der aktuelle Wert, laut Spezifikation (Stand Juni 2010) ein Pflichtattribut. Bei <html>5Doctor fand ich noch eine erweiterte Erklärung, hier heißt es: Wenn das Attribut nicht gesetzt ist, wird die erste gefundene Zahl innerhalb des Elements als value genutzt, gibt es keine Zahl, so ist der Wert Null.
  • Min: Der minimal erlaubte Wert (optional). Sollte kein Wert gesetzt sein, ist der Wert Null.
  • Max: Der maximal erlaubte Wert (optional). In manchen Fällen (bspw. bei Prozentangaben) ergibt sich der maximal Wert von allein. Ist keiner gesetzt ist er 1.
  • Low: Bestimmt den Anfangspunkt des unteren Abschnitts innerhalb der Gesamtspannweite (optional). Der Bereich zwischen Min und Low wäre die Ausprägung des unteren Abschnitts. Größer als der High Wert kann Low nicht sein.
  • High: Bestimmt den Anfangspunkt des oberen Abschnitts innerhalb der Gesamtspannweite (optional). Der Bereich zwischen Max und Low wäre die Ausprägung des oberen Abschnitts. Kleiner als der Low Wert kann High nicht sein.
  • Optimum: Bestimmt den optimalen Punkt des definierten Bereichs (optional). Dieser Punkt – soweit gesetzt kann jeden beliebigen Wert zwischen und inklusive Min und Max einnehmen
  • Ein spezielles Attribut für die zugrunde liegende Maßeinheit kennt das Meter Element (noch) nicht. Vorgeschlagen wird in diesem Falle das Universal-Attribut title zu nutzen.

Ein Beispiel

<p>Ihr Ergbnis:
  <meter min="0" low="4" high="8" value="7" optimum="10" max="10">
    7 von 10 Punkten
  </meter>
</p>

Die Semantik des Elements, der informative Mehrwert entsteht also nur durch die Attribute – und wie stellen Browser diese Informationen dar? Kurz: Bisher gar nicht – es gibt zwar Vorschläge wie ein Browser diese Informationen rendern könnte, aber passieren tut zur Zeit nichts. Wie weit kommt man mit CSS, um aus dem Meter Element mehr zu machen als die reine Textdarstellung? Auch nicht weit. CSS, so wie es die Browser momentan unterstützen fehlen dafür zwei entscheidene Möglichkeiten: Die Unterstützung von Attributen als Werte und die Möglichkeit Werte zu berechnen. Leider sind beide Eigenschaften in keinem aktuellen Browser implementiert. Mozilla meldet allerdings, dass es CALC() mit Firefox 4 unterstützen wird. Bis dahin ist eine reine CSS Lösung eine schöne Utopie. Als Basis für so eine zuküftige CSS basierte Lösung der Screenshot aus der Spezifikation:

Beispiel
Beispiel Screenshot aus der Spezifikation: HTML5 (Edition for Web Authors) – The meter element

Könnte man innerhalb von CSS rechnen, und dabei auf die Attribute des Elements zugreifen, dann ließe es sich bspw. wie folgt realisieren (eine Variante mit festen Werten findet man hier):

meter:before {
  height:4px;
  display:block;
  float:left;
  background:#d9d9d9;
  border-left:1px solid #4cb24c;
  /* Dynamische Ermittlung der Breite */
  width: 40 - calc((40 / 100) * (attrs(value) * 100));
  border-left-width:calc((40 / 100) * (attrs(value) * 100));
}

Wie gesagt, das ist Zukunftsmusik, wenn überhaupt, denn was calc leisten wird ist noch unklar. Reine CSS-Lösungen hätten ohne Frage den höchsten Freiheitsgrad in der Gestaltung, aber browserübergreifend kommt man nicht wirklich weit. Ein paar Beispiele habe ich hier zusammengestellt:

Beispiel Screenshots
Beispiel für eine CSS basierte meter Gestaltung in verschiedenen Browsersystemen

Die Screenshots zeigen, dass es zwar grundsätzlich möglich ist, die Gestaltung über CSS zu realisieren, aber selbst in aktuellen Browsersystem sind die Abweichungen zum Teil enorm. Der Internet Explorer 8 unterstützt ohne JavaScript noch gar kein html5 und würde demzufolge hier nur eine reine Textversion anzeigen. Da alle Werte “hart” gecodet werden müssen ist ein solcher Ansatz bis auf weiteres ohnehin obsolet. Was bleibt als Alternative? Man könnte das CSS mit Platzhaltern versehen, und diese serverseitig ersetzen. Dies würde die Darstellungsunterschiede aber auch nicht beseitigen. Serverseitig Bilder generieren wäre sicher auch eine Option, aber die Qualität solcher Bilder lässt zu wünschen übrig. Ein möglicher Ansatz wäre die Verwendung von Canvas, VML in Kombination mit JavaScript (auch wenn in solchen Fällen all die schöne Semantik wieder hin wäre).

Das Progress Element

Auch das Progress Element ist ein Inline-Element. Es ist eine quasi eine textuelle Repräsentation eines Fortschrittsbalken. Dabei kann er sowohl als Basis für eine dynamische Information (in Kombination mit JavaScript) oder statische Information (bspw. bei “Tunnel-Prozessen” wie einem mehrseitigen Formular) dienen. Die Spezifikation sagt:

The progress element represents the completion progress of a task. The progress is either indeterminate, indicating that progress is being made but that it is not clear how much more work remains to be done before the task is complete (e.g. because the task is waiting for a remote host to respond), or the progress is a number in the range zero to a maximum, giving the fraction of work that has so far been completed.

Letztlich unterscheiden sich das Progress Element und das Meter Element gar nicht so sehr voneinander. Wobei das Progress Element wohl noch wahrscheinlicher erst in Kombination mit JavaScript seine wahre Bedeutung erhält. Im Gegensatz zum Meter Element kennt Progress nur einen Anfgangs- und einen Endpunkt sowie den aktuellen Wert. Javascript basierte Lösungen für solche Fortschrittsbalken gibt es bereits einige, hier wäre eigentlich nur eine Schnittstelle zur Übernahme der Werte zu schaffen.

Seite 2 von 131234510...Ende