Custom Properties

CSS Custom Properties, auch CSS-Variablen genannt, speichern Werte unter einem selbstgewählten Namen. Dadurch können Farben, Abstände, Schriftgrössen oder andere Werte zentral definiert und im gesamten Stylesheet wiederverwendet werden.

Custom Properties sind live im Browser vorhanden. Sie können per Media Query, Klasse oder JavaScript zur Laufzeit verändert werden.


Syntax

Custom Properties werden mit zwei Bindestrichen (--) definiert und mit var() verwendet.

  • :rootWählt das Wurzelelement des Dokuments aus. Dort definierte Custom Properties stehen im gesamten Dokument zur Verfügung.
  • --nameDefiniert eine Custom Property.
  • var()Verwendet den Wert einer Custom Property.

Sinnvolle Namen: Variablennamen sind frei wählbar und sollten den Zweck des Werts beschreiben. Verwende beispielsweise --background, --text oder --spacing statt --white, --black oder --20px. So bleiben die Namen verständlich, wenn sich die gespeicherten Werte später ändern.

Variablen definieren

:root {
    --primary: rebeccapurple;
    --spacing: 20px;
    --radius: 8px;
}

Variablen verwenden

.button {
    background: var(--primary);
    padding: var(--spacing);
    border-radius: var(--radius);
}

Wichtig: Custom Properties sind case-sensitive. --Main-Color und --main-color sind zwei unterschiedliche Variablen.


Scope: Global und lokal

Custom Properties werden häufig auf :root definiert und gelten dann global für das gesamte Dokument. Sie können aber auch lokal auf einzelnen Elementen definiert werden und gelten dann nur für dieses Element und seine Nachfahren.

Erbt --accent von :root
Überschreibt --accent lokal
:root {
    --accent: rebeccapurple;
}

.card {
    border: 4px solid var(--accent);
}

/* Lokale Überschreibung – gilt nur innerhalb von .local */
.card.local {
    --accent: coral;
}

Custom Properties vererben sich wie normale CSS-Properties an Kindelemente – eine lokale Neudefinition wirkt sich nur auf das Element selbst und seine Nachfahren aus.


Fallback-Werte

var() kann einen zweiten Parameter (Fallback-Wert) erhalten. Dieser wird verwendet, wenn die Custom Property nicht definiert ist.

--missing-color ist nicht definiert
.element {
    background: var(--missing-color, limegreen);
    /* limegreen wird verwendet, weil --missing-color nirgends existiert */
}

Fallbacks können auch verschachtelt werden. Erst wenn keine der angegebenen Custom Properties existiert, wird der feste Wert verwendet: var(--a, var(--b, red)).


Skalen aufbauen

Custom Properties eignen sich ideal für einheitliche Abstands- oder Grössensysteme. Die Werte werden zentral definiert und im gesamten Stylesheet wiederverwendet.

--space-sm
--space-md
--space-lg
:root {
    --space-sm: 8px;
    --space-md: 16px;
    --space-lg: 32px;
}

.card {
    padding: var(--space-md);
    gap: var(--space-sm);
}

Light und Dark Mode

Farben mit light-dark() definieren

Mit light-dark() können einer Custom Property direkt zwei Farbwerte zugewiesen werden. Der Browser verwendet abhängig vom gewählten Farbschema den passenden Wert.

:root {
  color-scheme: light dark;

  --text: light-dark(#15130e, #f0eee9);
  --background: light-dark(#fbfaf9, #070605);
  --primary: light-dark(#594d3a, #c4b7a5);
  --accent: light-dark(#6c9461, #769f6b);
}

body {
  color: var(--text);
  background: var(--background);
}

a {
  color: var(--accent);
}

color-scheme: light dark informiert den Browser darüber, dass beide Farbschemata unterstützt werden. Bei light-dark() steht der erste Wert für den Light Mode und der zweite für den Dark Mode.

Variablen mit Media Query überschreiben

Innerhalb einer Media Query können Custom Properties neu definiert werden. Im Dark Mode lassen sich dadurch neben Farben beispielsweise auch Schriftgrössen oder Abstände verändern.

:root {
  color-scheme: light dark;

  --page-text: #2b2118;
  --page-background: #fff8e7;
  --link-color: #7950a8;
  --base-font-size: 1rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --page-text: #f5f1e8;
    --page-background: #14131a;
    --link-color: #9fcfff;
    --base-font-size: 1.05rem;
  }
}

body {
  color: var(--page-text);
  background: var(--page-background);
  font-size: var(--base-font-size);
}

a {
  color: var(--link-color);
}

Wechselt das Farbschema, werden die Variablen neu ausgewertet und alle damit gestalteten Elemente automatisch angepasst.


Media Queries mit Custom Properties

Custom Properties können innerhalb von Media Queries neu definiert werden. Alle Stellen, an denen die Variable verwendet wird, übernehmen den neuen Wert automatisch.

:root {
    --font-size-factor: 1;
}

h1 {
    font-size: calc(var(--font-size-factor) * 2.5rem);
}

@media screen and (min-width: 601px) {
    :root {
        --font-size-factor: 1.2;
    }
}

@media screen and (min-width: 901px) {
    :root {
        --font-size-factor: 1.5;
    }
}

calc() mit Custom Properties

Custom Properties können innerhalb von calc() für Berechnungen verwendet werden. Im folgenden Beispiel werden die Breite der Sidebar und der Abstand von der verfügbaren Gesamtbreite abgezogen.

:root {
    --sidebar-width: 250px;
    --gap: 20px;
}

.content {
    width: calc(100% - var(--sidebar-width) - var(--gap));
}

Details zu calc() selbst findest du in der calc()-Lektion.


@property

Ohne @property besitzt eine Custom Property keinen festgelegten Datentyp. Der Browser weiss deshalb nicht, ob der Wert beispielsweise eine Farbe, eine Länge oder ein Winkel ist.

Mit @property wird die Variable registriert und ihr Datentyp festgelegt. Dadurch kann der Browser den Wert prüfen und Veränderungen zwischen zwei Werten animieren.

  • syntaxLegt den erlaubten Datentyp fest, zum Beispiel <color>, <length> oder <angle>
  • inheritsLegt fest, ob die Custom Property an Kindelemente vererbt wird
  • initial-valueDefiniert den Anfangswert der Custom Property

Animierter Farbwechsel

Im folgenden Beispiel wird --box-color als Farbe registriert. Beim Hover ändert sich der Wert von hotpink zu rebeccapurple. Weil der Browser den Datentyp kennt, kann er den Übergang fliessend animieren.

Hover mich
@property --box-color {
  syntax: "<color>";
  inherits: false;
  initial-value: hotpink;
}

.property-demo {
  background: var(--box-color);
  padding: 2rem;
  transition: --box-color 0.5s;
}

.property-demo:hover {
  --box-color: rebeccapurple;
}

Datentyp <angle>

Dieses Beispiel verwendet den Datentyp <angle>, um einen kreisförmigen Farbverlauf zu animieren.

See the Pen @property Demo by Intensivstation (@intensivstation) on CodePen.


Live Theming – ohne JavaScript

Weil Custom Properties zur Laufzeit ausgewertet werden, reicht eine Checkbox mit :has(), um ein ganzes Farbschema umzuschalten.

Beispiel-Karte

Hintergrund, Text und Rahmenfarbe kommen alle aus Custom Properties.

<div class="theme">
    <label>
        <input type="checkbox" id="theme-toggle">
        Dark Mode
    </label>

    <div class="card">
        <h4>Beispiel-Karte</h4>
        <p>Hintergrund, Text und Rahmenfarbe kommen alle aus Custom Properties.</p>
    </div>
</div>
.theme {
    --bg: #fff;
    --text: #222;
    --accent: rebeccapurple;
}

.theme:has(#theme-toggle:checked) {
    --bg: #222;
    --text: #fff;
    --accent: coral;
}

.card {
    background: var(--bg);
    color: var(--text);
    border: 3px solid var(--accent);
    padding: 20px;
    transition: background .3s, color .3s, border-color .3s;
}

JavaScript & Custom Properties

Custom Properties können zur Laufzeit per JavaScript gelesen und geändert werden. Das eignet sich beispielsweise für Theme-Switcher oder interaktive Benutzeroberflächen.

// Wert setzen
document.documentElement.style.setProperty('--accent', 'coral');

// Wert auslesen
const value = getComputedStyle(document.documentElement)
    .getPropertyValue('--accent');

Cheat Sheet

  • --name: wert;Definiert eine Custom Property.
  • var(--name)Verwendet den Wert einer Custom Property.
  • var(--name, fallback)Legt einen Ersatzwert fest, falls die Custom Property nicht definiert ist.
  • :rootAuf dem Wurzelelement definierte Custom Properties stehen global zur Verfügung.
  • @propertyRegistriert eine Custom Property mit Datentyp, Anfangswert und Vererbungsverhalten.
  • syntaxLegt den Datentyp der Custom Property fest.
  • inheritsLegt fest, ob die Custom Property vererbt wird.
  • initial-valueDefiniert den Anfangswert.

Kurz gesagt

  • Custom Properties speichern Werte unter einem --name und werden mit var() verwendet.
  • Auf :root definierte Custom Properties stehen global zur Verfügung, auf einzelnen Elementen nur für das Element und seine Nachfahren.
  • Custom Properties können per Media Query, Klasse oder JavaScript zur Laufzeit verändert werden.
  • @property ermöglicht typisierte und animierbare Custom Properties.