iX 3/2017
S. 134
Praxis
Tipps & Tricks
Aufmacherbild

Die attr()-Funktion in CSS liest Text aus Attributen

Einfach gestrickt

Mit CSS lassen sich nicht nur statische Texte oder Symbole in HTML-Seiten einfügen. Dank einer Funktion können Stylesheets auch Inhalte von HTML-Attributen ausgeben.

Ein Mantra der modernen Softwareentwicklung lautet „Don’t repeat yourself“ – möglichst nichts wiederholen. Bei Web-Apps ist diese Maxime jedoch manchmal nicht so einfach umzusetzen. Wer etwa bei einem Link nicht nur einen Namen, sondern auch die URL selbst angeben möchte, könnte naheliegenderweise so etwas schreiben:

<a href="http://ziel.url">Ziel</a>
  (https://ziel.url)

oder auf JavaScript zurückgreifen, um die Ziel-URL beim Laden der Seite dynamisch hinzuzufügen. Ähnlich sieht es aus, wenn ein HTML-Dokument Daten für den schnellen Zugriff via JavaScript in data-Attributen verwaltet und sie gleichzeitig erscheinen sollen:

<span class="gewicht" 
 data-tara="10" data-unit="kg">
  10kg</span>

Seit CSS 2.1 bietet sich die Funktion attr() an, um in solchen und ähnlichen Fällen Wiederholungen zu vermeiden. Mit ihr kann man in den Pseudoselektoren ::before und ::after Text automatisch aus Attributen erzeugen lassen. Im ersten Fall stellt

a:after {
  content: " (" attr(href) ")"
}

sicher, dass hinter allen Links die URL in lesbarer Form erscheint. Wer diese Information nicht auf der Webseite, sondern nur im Druck sehen will, packt die Regel in einen @media-print-Abschnitt des Stylesheets.

Im zweiten Fall bietet sich eine Konstruktion wie die folgende an:

span.gewicht:after {
  content: attr(data-tara) attr(data-unit)
}

Listing 1: Listenelemente mit attr() formatieren

<!DOCTYPE html>
<html> <head>
<style>
li[data-typ]:before {
content: attr(data-typ);
font-size: smaller;
width: 5em;
display: inline-block;
}
li[data-typ] {
  list-style: none;
}
</style>
</head>

<body>
<ul>
<li data-typ="Obst">Äpfel</li>
<li data-typ="Gemüse">Rotkohl</li>
</ul>
</body>
</html>

Ähnlich lassen sich Listenelemente mit einem beschreibenden Text versehen, etwa bei Einkaufsnotizen (siehe Listing 1).

Allerdings sollte man die Technik gut überlegt verwenden. Denn den in :after- und :before-Regeln erzeugten Inhalt geben manche Screenreader nicht aus, weshalb die HTML-Seite nicht barrierefrei ist. So ignorierte Apples VoiceOver-Funktion jedenfalls in Safari, Chrome und Firefox die in diesen Pseudoselektoren erzeugten Texte. Die noch nicht abgeschlossene Definition von CSS3 sieht zwar vor, dass als letzter Teil einer content-Angabe nach einem Schrägstrich Text für die Ausgabe durch den Screenreader stehen darf. Das brachte jedoch Firefox und Chrome so aus dem Tritt, dass sie gar keinen Text mehr erzeugten. Safari zeigte in diesem Fall alles wie vorher an, und VoiceOver ignorierte den alternativen Text. Wenn Barrierefreiheit entscheidend ist, sollte man auf derart generierte Inhalte entweder verzichten oder sie auf Texte beschränken, die nicht essenziell für das Verstehen sind.

Noch mehr Power für attr()

Listing 2: attr() in CSS3

<!DOCTYPE html>
<html> <head>
<style>
.stuhl {
background: green;
}
.tisch {
background: blue;
}
div.stuhl, div.tisch {
  width:attr(data-count em);
  height: 1em;
  margin-left: 0.5em;
}
</style>
</head>
<body>
<div class="stuhl" data-count="10">Stuhl 1</div>
<div class="stuhl" data-count="5">Stuhl 2</div>
<div class="tisch" data-count="7">Tisch 1</div>
<div class="tisch" data-count="15">Tisch 2</div>
</body>
</html>

In CSS3 könnte die attr()-Funktion noch wesentlich leistungsfähiger werden, wenn sie es denn in den Standard schafft. Das ist bislang noch unklar. Bleibt es bei dem Vorschlag, wäre attr() für das Setzen nahezu jeder CSS-Eigenschaft verwendbar. So könnte man etwa eine simple Balkengrafik mit dem Code aus Listing 2 ausgeben. Es zeigt wie bisher den Zugriff von attr() auf ein data-Attribut. Diesmal folgt jedoch die Längeneinheit em, und eine Kombination aus Wert und Einheit definiert die Breite (width) des div-Elements. Je nach betroffenem Style-Attribut kann die Einheit neben Dimensionsangaben color, url oder % sein. Ausprobieren lässt sich das bislang nicht ohne Weiteres, denn kein aktueller Browser unterstützt diese Möglichkeiten zurzeit.

Auf CodePen gibt es ein Polyfill, das eine CSS3-konforme attr()-Funktion nachbilden soll. Mit zwei von drei dort veröffentlichten Beispielen funktioniert das auch. Allerdings ist der JavaScript- stark mit dem HTML-Code verwoben, sodass das Einbinden in eine eigene Anwendung aufwendig sein dürfte. (tiw)