Normalerweise besteht die Verbindung zwischen CSS und HTML darin, dass CSS-Selektoren HTML-Elemente auswählen und CSS diese stilisiert. CSS kennt den tatsächlichen Inhalt in HTML nicht. Aber es gibt einen Weg, wie CSS an Daten in HTML gelangen kann, solange diese Daten in einem Attribut dieses HTML-Elements enthalten sind.
Es ist so
div::after {
content: attr(data-whatever);
}
Das ist sicherlich interessant. Man könnte es zum Beispiel für (eher unzugängliche) Tooltips verwenden.
<button data-tooltip="Information only mouse-having sighted people will see.">
Button
</button>
button:hover::after {
content: attr(data-tooltip);
/* positioned and styled and whatnot */
/* ya, a :focus style would buy you a tad more a11y */
}
Aber man kann keinen HTML-Code in den Attributwert einfügen, daher sind diese Tooltips auf einen String-Wert beschränkt und könnten keinen Titel, Link oder ähnliches enthalten.
Hier ist ein besserer Anwendungsfall. Es gibt eine alte Marotte für Print-Stylesheets, bei der man attr() verwendet, um die URLs zu Links hinzuzufügen, damit man tatsächlich sehen kann, wohin ein Link führt.
@media (print) {
a[href]::after {
content: " (" attr(href) " )";
}
}
Das ist clever. Aber was noch? Könnte man eine Farbe weitergeben?
<h2 data-color="#f06d06">
Custom Colored Header
</h2>
Das ist nicht ungültig, aber es ist nicht nützlich.
h2 {
/* Not gonna work */
color: attr(data-color);
}
Der Wert von attr() ist ein String. Auch wenn dieser String im gleichen Format wie ein Hex-Code vorliegt, wird er nicht als Hex-Code verwendet.
Man kann auch keine URL übergeben, die tatsächlich in etwas wie background-image() verwendet werden kann. Man kann auch keine Einheit wie 3, 20px oder 4rem oder 0.8vw übergeben.
Die attr()-Funktion von CSS ist nur für Strings, und Strings sind nur wirklich nützlich für content, und content (da es nicht auswählbar und etwas unzugänglich ist) ist sowieso nicht besonders nützlich. Man kann zum Beispiel den Text von Pseudoinhalten nicht auswählen oder danach suchen, was ihn ziemlich unzugänglich macht.
Weißt du, was jeden beliebigen Wert übergeben kann und genauso einfach zu implementieren ist wie Attribute?
CSS-benutzerdefinierte Eigenschaften!
Man kann sie direkt in das style-Attribut jedes Elements einfügen. Jetzt sind diese Werte für dieses Element verfügbar.
<button
style="
--tooltip-string: 'Ug. Tooltips.';
--tooltip-color: #f06d06;
--tooltip-font-size: 11px;
--tooltip-top: -10px
"
>
Button
</button>
Oben übergeben wir einen String an CSS, aber auch Farb- und Längenwerte. Diese Werte sind sofort einsatzbereit.
button::after {
content: var(--tooltip-string);
color: var(--tooltip-color);
font-size: var(--tooltip-font-size);
}
Hier ist diese Demo mit etwas fummeliger "Logik" (müsste stark verbessert werden, um wirklich nützlich zu sein), um Variationen zu ermöglichen.
Siehe den Stift CSS Custom Properies Mo’ Betta’ than attr() von Chris Coyier (@chriscoyier) auf CodePen.
Das ist im Übrigen auch nicht zugänglicher. Wenn ich Tooltips wirklich implementieren würde, würde ich dies hier gründlich lesen.
Was ist mit anderen "guten" Anwendungsfällen für attr()?
Einer, der oft vorkommt, sind responsive Datentabellen. Stellen Sie sich eine Tabelle mit Kopfzeilen in der obersten Zeile und Datenzeilen darunter vor.
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
....
</tr>
</thead>
<tbody>
<tr>
<td>Chris</td>
<td>Coyier</td>
...
</tr>
...
</tbody>
</table>
Datenzeilen wie diese können auf kleinen Bildschirmen problematisch werden (zu breit). Daher könnten wir in einer responsiven Datentabelle diese oberste Zeile ausblenden und stattdessen Labels zellenbasiert anzeigen.
@media (max-width: 500px) {
thead {
display: none;
}
/* Need to reveal another label now that we've hidden the normal labels */
}
Woher kommt dieses Label? Wir könnten es so machen…
. ...
<tr>
<td data-label="First Name">Chris</td>
<td data-label="Last Name">Coyier</td>
...
</tr>
Dann
td::before {
content: attr(data-label);
/* Also display: block things and such */
}
Das ist ein ziemlich guter Anwendungsfall. Wenn wir eine Art zugängliche Verbergungsmethode für dieses <thead> verwenden, könnte es sogar die Zugänglichkeitsprüfung bestehen.
Aber genau dasselbe ist auch mit CSS-benutzerdefinierten Eigenschaften machbar…
. ...
<tr>
<td style="--label: 'First Name';">Chris</td>
<td style="--label: 'Last Name';">Chris</td>
...
</tr>
td::before {
content: var(--label);
...
}
Eric Bidelman verwies mich auf eine Methode, Pseudoinhalt zu verwenden, um den Wert eines Eingabefeldes anzuzeigen.
<style>
input {
vertical-align: middle;
margin: 2em;
font-size: 14px;
height: 20px;
}
input::after {
content: attr(data-value) '/' attr(max);
position: relative;
left: 135px;
top: -20px;
}
</style>
<input type="range" min="0" max="100" value="25">
<script>
var input = document.querySelector('input');
input.dataset.value = input.value; // Set an initial value.
input.addEventListener('change', function(e) {
this.dataset.value = this.value;
});
</script>
Das fühlt sich für mich etwas gefährlich an, da ich nicht dachte, dass Pseudoinhalt bei ersetzten Elementen wie einem <input> funktionieren würde. Es ist wahrscheinlich eine Aufgabe für output, und die JavaScript-Logik wäre im Wesentlichen dieselbe. Man könnte Pseudoinhalt mit dem zusätzlichen Element verwenden, aber das ist wirklich nicht nötig.
Die Tatsache auszunutzen, dass Pseudoinhalt nicht kopiert werden kann, ist ebenfalls clever. Zum Beispiel macht GitHub Zeilennummern für Codeblöcke mit data-line-number="" und ::before { content: attr(data-line-number); }.

Niemand mag es, Zeilennummern auszuwählen, wenn er versucht, Code zu kopieren! Guter Anwendungsfall hier (wahrscheinlich sogar flexibler als CSS-Zähler), aber auch hier etwas, das CSS-benutzerdefinierte Eigenschaften ebenfalls handhaben könnten.
<td style="--line-num: 5"> ... </td>
Man könnte argumentieren, dass dies besser ist, denn wenn man CSS-Zähler verwenden möchte, könnte man diesen ersten Wert verwenden, um den Startpunkt festzulegen und ihn nicht auf jeder Zeile zu benötigen.
Siehe den Stift Line Numbering von Chris Coyier (@chriscoyier) auf CodePen.
Das Gleiche gilt für typografische Tricks, bei denen Text aus stilistischen Gründen in CSS dupliziert wird. Sehen Sie sich diese coole Demo von Mandy Michael mit attr() an. Ich bin sicher, Sie können sich vorstellen, wie --heading: "Fracture"; die Sache dort erledigen könnte.
Die CSS3 Values-Spezifikation (in Candidate Recommendation) bietet eine Möglichkeit, attr() nützlich zu machen.
Ich bin mir nicht sicher, ob das viel ausmacht, da ich argumentieren würde, dass CSS-benutzerdefinierte Eigenschaften ein nahezu vollständiger Ersatz für attr() sind, aber die Spezifikation behandelt dies ausdrücklich, vermutlich als Versuch, sie nützlicher zu machen.
Die Idee ist, den Typ des Wertes festzulegen, wenn man ihn in CSS abruft.
<div data-color="red">Some Words</div>
div {
color: attr(data-color color);
}
Oder…
<span data-size="50">span</span>
span {
font-size: attr(data-size px);
}
Aber soweit ich weiß, unterstützt kein Browser dies.
Das ist keine CSS-Tricks. Das ist in den Bereich der CSS-schwarzen Magie eingetreten.
+1 CSS WIZARD
Ich habe die attr()-Funktion gestern in Kombination mit einem abbr-Tag verwendet. Es erforderte etwas Feinarbeit, aber auf Mobilgeräten wird die Abkürzung angezeigt und auf Tablet- und Desktop-Größen das volle Wort. Wurde verwendet, um ein Datum mit Wochentagen und Monaten anzuzeigen.
Ich verstehe vollkommen, worauf Sie hinauswollen, aber ab welchem Punkt macht es mehr Sinn, einfach wieder zu Inline-Styles zurückzukehren? Ich schätze, es macht mehr Sinn, benutzerdefinierte Eigenschaften zu verwenden, wenn Sie den Wert an mehreren Stellen wiederverwenden müssen, aber in den aufgeführten Beispielen könnten Sie die Stile einfach inline schreiben.
Ich stimme zu, das führt zurück zur Verwendung von Inline-Styles, und Inline-Styles wären einfacher. Ich denke, die Verwendung von benutzerdefinierten Eigenschaften fügt nur den Coolness-Faktor hinzu.
Stimmt – aber es hilft sehr, wenn man Eigenschaften für Pseudoelemente bereitstellen möchte. Hat mir ein langjähriges Designproblem gelöst – eine transparente Hundeohrecke https://codepen.io/scootman/pen/XzpbGK. Möglich ohne benutzerdefinierte Eigenschaften – aber das HTML ist sehr ausführlich.
Bezüglich des Tooltip-Beispiels fühlt sich das Einfügen von Inhalt in einen Inline-Stil für diesen Workaround mit benutzerdefinierten Eigenschaften viel zu hacky an. Wäre es nicht einfacher und zugänglicher, so etwas zu tun?
Versteh mich nicht falsch – die Inline-Styles mit benutzerdefinierten Eigenschaften sind ein cleverer Trick für Nicht-String-Elemente, aber die zweite Version des von Ihnen gegebenen Beispiels ist genauso unzugänglich wie die erste.
Ja, benutzerdefinierte Eigenschaften bringen durch ihre bloße Verwendung keine Zugänglichkeit. aria-label scheint ein ziemlich gutes Attribut dafür zu sein! Sicherlich besser als
title, dessen Stil man nicht kontrollieren kann.Ich denke, aria-label ist hier das Beste. Danke für den Tipp.
Schauen Sie, attr kann innerhalb von jQuery verwendet werden. Zum Beispiel, wenn Sie den Hintergrund eines Icons ändern möchten, können Sie mit attr spielen. Ich zeige Ihnen
$(“#button”).on(“mouseenter”, function(e) {
$(this).animate….attr(“diffuse-color”, “red”); });
Dies animiert den Hintergrund. Verwenden Sie den Testfall.
Ich denke, Sie versuchen zu sagen: JavaScript kann auf den Wert eines Attributs zugreifen und den Wert in der von Ihnen beabsichtigten Weise verwenden, zum Beispiel einen String als Farbwert.
Ja, JavaScript kann das.
Was ist mit CSP?
Content Security Policy?
Möchten Sie das näher erläutern?
Die CSS3 Values-Spezifikation ist besser, da sie es uns ermöglicht, Attribute festzulegen/zu entfernen, ohne Strings aus dem einzigen style-Attribut extrahieren zu müssen.
a11y?!
W1y?
;)
Übrigens liebe ich das Oberteil. Und stimme Goose zu, dass es schwarze Magie ist! Meine Lieblingsart von Tipp. :)
Schöne Beispiele, besonders das @media (print)-Beispiel für Links gefiel mir, hatte ich vorher noch nie gesehen oder darüber nachgedacht, echt cool! :D
Ich habe 3 Dinge aus diesem Artikel gelernt.
attr()gibt immer nur einen String zurück, weshalb es nicht für Farben usw. funktioniert. Jetzt verstehe ich lolDie Existenz von
counter-resetundcounter-incrementEigenschaften. Großartig!Man kann benutzerdefinierte Eigenschaften im
style-Attribut überschreiben. Wieder großartig!Danke Chris.
Ein Anwendungsfall, den Sie vermissen – der nur von der neuen Spezifikation abgedeckt würde – ist das elegantere Festlegen von CSS-Variablen.
Z. B. auf einem Raster (ich bin sicher, es gibt bessere Anwendungsfälle, z. B. das Übergeben einer dynamischen Farbe über ein Attribut).
Beispiel unter: https://jsfiddle.net/nilssolanki/z7r46n8k/