Das echte SELFHTML-Wiki gibt es unter https://wiki.selfhtml.org.
CSS/Custom properties (CSS-Variablen)
Text-Info

- 20min

- leicht → mittel

- Einstieg in CSS
Mit custom properties (benutzerdefinierten Eigenschaften) können Sie einen Wert an einer Stelle festlegen, auf den dann an mehreren anderen Stellen verwiesen wird. Ein weiterer Vorteil sind semantische Bezeichner. So ist beispielsweise --main-text-color leichter zu verstehen als #00ff00, vor allem, wenn dieselbe Farbe auch in anderen Kontexten verwendet wird.
Vorläufer für den Einsatz von Variablen in CSS waren Präprozessoren wie SASS, die aber einige Nachteile haben:
- Sie werden vor dem Laden des Dokuments zusammengestellt und können deshalb nicht auf Änderungen durch media queries reagieren
- Sie können nicht von JavaScript ausgelesen oder verändert werden.
Custom Properties dagegen …
- reagieren unmittelbar auf Änderungen im DOM und auf media queries
- reagieren auf die Elementschachtelungen im DOM
- ermöglichen es, mit setProperty() ein individuelles Theme anzubieten
Oft als CSS-Variablen bezeichnet, sind custom properties doch keine Variablen im eigentlichen Sinne.
Inhaltsverzeichnis
Syntax
Custom properties (benutzerdefinierte Eigenschaften) bestehen aus zwei Bestandteilen:
- Einer benutzerdefinierten Eigenschaft wird ein Wert zugewiesen. Der frei gewählte Name dieser Eigenschaft beginnt mit zwei Minuszeichen. Es gibt zwei mögliche Stellen für diese Zuweisung:
- Dieser Wert wird später mit der CSS-Funktion var() beliebig oft wieder aufgerufen.
Details: caniuse.com
:root {
--akzentfarbe: #c32e04;
}
h1 {
border: thin solid var(--akzentfarbe);
}
h1::before {
color: var(--akzentfarbe);
content: "Wichtig: ";
}
- Im Gegensatz zu regulären Eigenschaften ist der Name eines Custom Property case-sensitive, d. h. die Namen
--selfund--Selfbezeichnen unterschiedliche Eigenschaften. - Der Name eines Custom Property kann jedes Unicode-Zeichen enthalten, sogar Emojis. Vermeiden Sie Zeichen, die in Stylesheets eine Sonderbedeutung haben. Sie müssten sie mit einem vorangestellten \ Zeichen maskieren.
- Variablen können nur Werte, aber keine Eigenschaften annehmen.
- Beim Funktionsaufruf darf sich innerhalb der Klammer kein Leerzeichen befinden.
Mittlerweile unterstützen alle Browser außer dem IE9-11 custom properties und ein Fallback ist daher eigentlich nicht mehr nötig, kann aber als eindeutige Festlegung nach der CSS-Variable notiert werden:
h1 {
color: var(--akzentfarbe, red);
}
Ältere Browser, die
var() nicht verstehen, ignorieren auch diese Angabe und rendern dafür die Elemente in den Standardeinstellungen.Zusätzlich gibt es mit ShadyCSS einen Polyfill, der besonders für Web Components geeignet ist.
Anwendungsbeispiele
Die folgenden Beispiele zeigen, dass man mit custom properties viel mehr als nur Farben festlegen kann:
Anwenden einer Farbpalette
:root {
--primary: #666;
--hintergrund: #ccc;
--akzent: #c32e04;
--linkfarbe: #09c;
}
h2 {
color: var(--primary);
border-bottom: medium solid var(--akzent);
}
aside {
color: var(--akzent);
background-color: var(--primary);
border: medium solid var(--akzent);
}
aside > h2 {
color: var(--hintergrund);
border-bottom: medium solid transparent;
}
aside > label {
color: black;
background-color: var(--akzent);
}
ein maßgeschneidertes Theme
Mit den custom properties können nicht nur Farben, sondern auch Farbtöne und -variationen erzeugt werden[2]:
:root { --akzentfarbe: 195, 46, 4 }
h1 { color: rgb(var(--akzentfarbe)) }
h2 { color: rgba(var(--akzentfarbe), 0.5) }
Für h2 wird die Akzentfarbe als rgba-Wert mit einem Transparenzwert von 0.5 (50% Deckkraft) berechnet.
Noch mehr Möglichkeiten ergeben sich bei der Verwendung von HSL-Werten[3]:
:root {
--baseHue: 240;
--primary: hsl(var(--baseHue), 80%, 40%);
--accent1: hsl(calc(var(--baseHue) - 231), 80%, 40%);
--backgr1: hsl(calc(var(--baseHue) - 231), 80%, 40%,.15);
--accent2: hsl(calc(var(--baseHue) - 200), 80%, 50%);
--backgr2: hsl(calc(var(--baseHue) - 200), 80%, 50%,.15);
}
baseHue festgelegt und für die Akzentfarben mit der calc()-Funktion entsprechend verändert. Für die Akzentfarben gibt es noch hellere Töne für den Hintergrund. Insgesamt ist die Farbpalette an die SELFHTML-Farbtabelle angelehnt.document.addEventListener('DOMContentLoaded', function () {
document.querySelector('#huePicker').addEventListener('input', setHue);
});
function setHue() {
const root = document.querySelector(':root');
var huePicker = document.querySelector('#huePicker');
root.style.setProperty('--baseHue', huePicker.value);
};
baseHue zugewiesen.Das Beispiel von Keith Clark verwendet Farbwähler (input type="color"), mit denen eine Hauptfarbe und eine Kontrastfarbe ausgewählt werden.
Countdown
Bis jetzt benötigten Sie JavaScript, um einen Countdown herunterzuzählen. Mit custom properties können Sie dies nur mit CSS erreichen.[4]
<div class="time-bar" style="--duration: 9;">
<div></div>
</div>
Als Zeitleiste wird ein div verwendet (ein meter-Element wäre evtl. semantisch passender, bringt jedoch bereits viele eigene Formatierungen mit).
.time-bar div {
height: 1em;
background: linear-gradient(to bottom, red, #c32e04);
animation: roundtime calc(var(--duration) * 1s) steps(var(--duration)) forwards;
transform-origin: left center;
}
@keyframes roundtime {
to {
/* More performant than animating `width` */
transform: scaleX(0);
}
}
Bereits im HTML wurde im style-Attribut des Container-divs eine CSS-Variable --duration festgelegt.
Sie wird nun 2x verwendet:
- steps zerlegt die Animation in einzelne Schritte, ohne extra Wegpunkte festlegen zu müssen.
- animation-duration erfordert einen Wert mit Zeiteinheit:
calc(var(--duration) * 1s)fügt an die Zahl die Einheitsan.
SVG und CSS
Längeneinheiten und custom properties
In HTML benötigen Elemente normalerweise keine Positionierung, da sie nacheinander im Elementfluss liegen. SVG-Objekte werden jedes für sich gezeichnet und positioniert. Bei mehreren Objekten mit jeweils gleichem Abstand zueinander müssen die Koordinaten immer wieder neu berechnet werden. Dies geht mit CSS einfacher:
.ball {
--distance: calc(var(--d, 1) * (2.5 * var(--radius)));
--radius: 20px;
cx: var(--distance);
cy: var(--radius);
r: var(--radius);
}
.ball:nth-child(1) {
fill: var(--color-1);
}
.ball:nth-child(2) {
fill: var(--color-2);
--d: 2;
}
.ball:nth-child(3) {
fill: var(--color-3);
--d: 3;
}
...
Das Beispiel enthält drei custom properties:
-
--radiuserhält einen festen Pixelwert von 20px. (Eigentlich besteht das Koordinatensystem von SVG aus dimensionslosen Einheiten; Firefox benötigt bei Geometrieattributen in CSS eine Angabe in Pixeln.) -
--var-distancebesteht aus einer längeren Berechnung mit calc():-
(2.5 * var(--radius)verwendet den eben erwähnten Radius und multipliziert ihn mit einem Faktor 2.5. Dieser Wert wird z.B. für den Abstand des ersten Balls zum linken Rand benötigt. -
calc(var(--d, 1) * ...)multipliziert das obere Zwischenergebnis mit einer Variable--d
-
- Die Variable
--dwird per CSS über den nth-child immer wieder neu gesetzt.
Die Berechnung von --distance löst ein vermeintliches Problem von custom properties, dass das Hinzufügen von Einheiten wie in JavaScript nicht möglich wäre:[5]
.icon {
--scale: 1;
/* this doesn't work */
font-size: var(--scale) + 'px';
}Mit Hilfe der calc()-Funktion gelingt dies problemlos:
.icon {
--scale: 1;
/* this works */
font-size: calc(var(--scale) * 1rem);
}SVG mit CSS-Animationen
Auch in CSS-Animationen gibt es z.B. bei Verzögerungen Werte, die aufeinander aufbauen.
.ball {
--delay: calc(var(--i, 1) * 100ms);
--distance: calc(var(--d, 1) * (2.5 * var(--radius)));
--radius: 20px;
cx: var(--distance);
cy: var(--radius);
r: var(--radius);
animation: moveCircle 1200ms var(--delay) ease-in-out infinite;
}
.ball:nth-child(1) {
fill: var(--color-1);
}
.ball:nth-child(2) {
fill: var(--color-2);
--d: 2;
--i: 2;
}
.ball:nth-child(3) {
fill: var(--color-3);
--d: 3;
--i: 3;
}
Wie im oberen Beispiel setzt sich die Variable --delay aus einer Berechnung zusammen: Die Zählvariable --i wird über den nth-child-Selektor immer wieder neu gesetzt und mit einem gegebenen Zeitwert (von hier 100ms) multipliziert.
Leider muss diese Variable --i wie auch --d immer wieder explizit gesetzt werden. Um die Anzahl der Objekte automatisch zu erfassen, müsste man JavaScript einsetzen. Deshalb gibt es einen Vorschlag eine sibling-count()-Funktion einzuführen, die dies bereits im CSS erledigen könnte.[6]
clip-path und vendor-prefixes
Eine der Begleiterscheinungen von CSS3 waren die Browserpräfixe, die den damals neuen Eigenschaften vorangestellt wurden. Heute gibt es nur noch wenige Eigenschaften, die z. B. ein zusätzlichen Regelsatz mit -webkit- benötigen.
Bei Beschneidungen erfordert ein Einsatz der clip-path-Eigenschaft solch einen doppelten Regelsatz. Damit bei einer späteren Anpassung der Wert nur einmal geändert werden muss, können auch hier Custom properties helfen:
.img {
--clip: polygon(0 0, 100% 0, 50% 100%, 0 100%);
-webkit-clip-path: var(--clip);
clip-path: var(--clip);
}
Der Wert wird als CSS-Variable --clip festgelegt und beiden Regelsätze zugewiesen.
Noch besser wäre es, wenn man den Beschneidungspfad selbst durch custom properties vereinfachen könnte. Michelle Barker zeigte das in diesem CodePen.[7]
Weiterführendes
Benutzerdefinierte Eigenschaften verhalten sich genau wie normale, vererbbare CSS-Eigenschaften: Sie sind auch auf Kind-Elementen verfügbar und sie beachten die Regeln für Kaskade und Spezifität, d.h. benutzerdefinierte Eigenschaften, die an einer Stelle festgelegt werden, können durch eine spezifischere Regel überschrieben werden.
Zusammenspiel der Regeln
Eine wichtige Eigenschaft von custom properties ist, dass var() aufgelöst wird, wenn die Eigenschaft, die die var()-Angabe enthält, auf ein HTML- oder SVG-Element angewendet wird. Wird die so gesetzte Eigenschaft weiter vererbt, ist der Wert festgelegt und nicht mehr variabel.
<style>
body { --farbe: red; }
ul { color: var(--farbe); }
li { --farbe: blue; }
</style>
<body>
Hallo
<ul>
<li>Welt</li>
<li>Selfhtml</li>
</ul>
</body>
- Der body erhält eine custom property
--farbe. - Das
ul-Element erhält für die Eigenschaftcolorals Wert den berechneten Wert der custom property--farbe. Dieser wird, falls es keine spezifischeren Festlegungen gibt, an die Kindelemente weitervererbt. - Für
liwird der Wert für--farbeneu gesetzt.
Lösung anzeigenverbergenFür li wird der Wert für --farbe neu gesetzt.
Allerdings wurde der neue Wert color-Eigenschaft noch nicht zugewiesen; deshalb wird der vorher zugewiesene Wert für ul vererbt.
→ Die li-Elemente werden rot dargestellt.
<style>
p { color: var(--farbe); }
section.a { --farbe:red; }
section.b { --farbe:blue; }
</style>
<body>
<section class="a">
<p>Hallo Welt</p>
</section>
<section class="b">
<p>Hallo Welt</p>
</section>
<p>Absatz außerhalb einer section</p>
Hier ist es so, dass die erste CSS Regel auf beide p Elemente innerhalb der section-Elemente angewendet wird, aber jeweils im Moment der Anwendung unterschiedliche Werte für --farbe vom section-Element vererbt werden. Deswegen wird der erste Abschnitt rot dargestellt und der zweite Abschnitt blau.
Sind das jetzt Variablen?
Auch wenn es immer wieder heißt, dass Custom properties keine Variablen wären, werden die beiden Begriffe oft nebeneinander benutzt:[8]
Custom properties (sometimes referred to as CSS variables or cascading variables) … You can define multiple fallback values when the given variable is not yet defined.
MDN: Using CSS custom properties (variables)[9]
Custom properties (sometimes referred to as CSS variables or cascading variables) … You can define multiple fallback values when the given variable is not yet defined.
MDN: Using CSS custom properties (variables)[10]
Information: Variablen
In Programmiersprachen sind Variablen abstrakte Behälter für eine Größe, welche im Verlauf eines Rechenprozesses auftritt. Im Normalfall wird eine Variable durch einen Namen bezeichnet und hat eine Adresse im Speicher einer Maschine.
Auch die Spezifikation verwendet den Begriff Variable, unterscheidet aber: Eine benutzerdefinierte Eigenschaft ist keine Variable, ermöglicht aber die Festlegung einer Variable.
Jede Eigenschaft kann mit der var()-Funktion Variablen verwenden, deren Werte durch die zugehörigen benutzerdefinierten Eigenschaften definiert sind.
Die benutzerdefinierte Eigenschaft --accent-background verwendet die Variable var(--main-color), deren Wert durch die benutzerdefinierte Eigenschaft --main-color definiert ist.
Was noch nicht geht
Man kann (Stand 2021/06) eine custom property nicht innerhalb einer media query benutzen, z.B.
@media (max-width: var(--mobile-breakpoint)) {...},
sondern nur innerhalb der geschweiften Klammern.
Siehe auch
- fertige Layouts/Design01
ein Beispiel-Layout mit einem „normalen“ und einem dunklen Theme im Dark Mode - die SVG-Uhr, die die Zeit mit CSS-Variablen setzt
- HTML/Tabellen/Responsive Gestaltung – responsive Tabellen erhalten mit custom properties benutzerfreundliche Spaltenüberschriften
- CSS-Formatierung des Shadow DOM
Das SVG-Use-Element kann aus beliebig vielen Teil-Elementen bestehen, die im Shadow DOM vorhanden sind, aber nicht durch CSS formatiert werden können. MIt Custom properties können auch einzelne Bestandteile des use-Elements formatiert werden.
Quellen
- ↑ CSSWG: Using Cascading Variables: the var() notation
- ↑ SELF-Forum: Farben in Abhängigkeit von Grundfarbe von Gunnar Bittersmann vom 05.03.2020
- ↑ SELF-Forum: Farben in Abhängigkeit von Grundfarbe von Rolf B. vom 05.03.2020
- ↑ css-tricks.com: Timer Bars in CSS with Custom Properties von Chris Coyier, Aug 18, 2020
- ↑ How to append a unit to a unitless css custom property with calc() Kevin Powell, 17.03.2019
- ↑ github.com: [css-values] Proposal: add sibling-count() and sibling-index() Vorschlag vom 04.12.2019
- ↑ CSS {In Real Life}: 7 Uses for CSS Custom Properties vom 09.12.2019
- ↑ webplatformnews: CSS custom properties are not variables
- ↑ MDN: Using CSS custom properties (variables)
- ↑ MDN: Using CSS custom properties (variables)
- ↑ Wikipedia: Variable (Programmierung)
Weblinks
- csswg: Defining Custom Properties: the --* family of properties (Entwurf)
- MDN: Using CSS custom properties (variables)
- css-tricks: Simplifying CSS Cubes with Custom Properties von Ana Tudor
- sitepoint: A Practical Guide to CSS Variables (Custom Properties) (15.06.2017)
Zikaden-Prinzip für unregelmäßig wirkende Strukturen
- The Cicada Principle, revisited with CSS variables Lea Verou, 07.07.2020
--akzentfarbeund ist durch die zwei vorangestellten Minuszeichen als custom property erkennbar.Anschließend kann diese Variable im gesamtem Stylesheet mit der Funktion
var()wieder aufgerufen werden.[1].