Gelegentlich hört man die Ansicht, CSS entwickle sich immer mehr zu einer “richtigen” Programmiersprache. Und tatsächlich gibt es Diskussionen, ob zumindest die Kombination aus HTML und CSS 3 Turing-vollständig sein könnte. Ohne zu sehr auf die theoretischen Hintergründe einzugehen: Als “Turing-vollständig” bezeichnet man Rechensysteme (z. B. Programmiersprachen), die theoretisch alles berechnen können, was irgendein Computer berechnen kann - unbegrenzte Ressourcen an Speicher, Rechenzeit usw. vorausgesetzt. Und eine “richtige” Programmiersprache muss, zumindest wenn man eine strikte Definition anlegt, eben Turing-vollständig sein.

In der Praxis heißt das, sie muss Informationen aus dem Speicher lesen und in den Speicher schreiben können (z. B. in Form von Variablen), sie muss Anweisungen beliebig oft wiederholen können (etwa mit while-Schleifen) und sie muss Entscheidungen anhand von Daten treffen können (beispielsweise in if-else-Verzweigungen). Und zumindest das letzte bekommt CSS gerade in gewisser Weise, nämlich eine if()-Funktion.

Diese Funktion wird Stand Anfang April 2026 vor allem von Chrome-basierten Browsern unterstützt. Zum Baseline-Status fehlen noch Firefox und Safari. Aber interessant ist sie allemal.

In einer if()-Funktion listet man sogenannte “if branches” auf. Ein solcher Zweig kann eine Bedingung enthalten, oder schlicht else sein. Außerdem enthält jeder Zweig einen Wert. Der Wert des ersten Zweigs, der zu true ausgewertet wird, bestimmt den Wert der ganzen Funktion.

In der Praxis sieht das beispielsweise so aus:

.card {
    width: if(media(width < 1024px): 75px; else: 150px;);
}

Wenn der Viewport weniger als 1024px breit ist, wird das ausgewertet zu

.card {
    width: 75px;
}

ansonsten zu

.card {
    width: 150px;
}

Die Anzahl der Zweige ist beliebig, man kann also beispielsweise auch etwas schreiben wie

.card {
    width: if(media(
      width < 1024px): 75px;
      media(width < 1280px): 100px;
      else: 150px;
    );
}

(Das syntax highlighting kommt hier noch nicht ganz mit der noch ziemlich neuen Syntax zurecht)

In diesem Fall genügt es, die zweite Bedingung als “kleiner 1280px” zu formulieren, man braucht kein “1024px ≥ width < 1280px” - der erste Zweig hat ja bereits alles unterhalb von 1024px erledigt. Der else-Zweig muss nicht zwingend am Ende stehen. Da ein else-Zweig aber grundsätzlich als true ausgewertet wird, kämen alle Zweige danach nie zum Zuge und wären überflüssig.

Für die Bedingungen gibt es drei Möglichkeiten: Mit einer media query kann man Informationen über das Device abfragen, beispielsweise die Maße des Viewports, die Orientierung (landscape oder portrait) oder den Medientyp (zum Beispiel color: if (media(print): black);).

Mit einer feature query bezieht man ein, was der Browser unterstützt. Man kann beispielsweise eine Farbe im LCH-Farbraum angeben, wenn der Browser damit umgehen kann, und sonst auf einen RGB-Wert zurückfallen:

.card {
    color: if(
      supports(color: lch(7.1% 60.23 300.16): lch(7.1% 60.23 300.16);
      else: #03045E;
    );
}

Eine style query wiederum bezieht sich auf den Wert einer CSS-Variablen:

<section class="intro">
    <div class="card">Card in intro</div>
</section>

<section class="main">
    <div class="card">Card in main</div>
</section>
.intro {
    --card-type: "intro";
}

.main {
    --card-type: "main";
}

.card {
    font-weight: if(
      style(--card-type: intro): bold; 
      else: normal;
    );
}

Diese Möglichkeit ist nicht zuletzt im Zusammenspielt mit der Funktion attr() praktisch, weil man HTML-Attribute sehr leicht mit JavaScript verändern kann:

<div class="card" data-status="pending">
    A card still pending
</div>

<div class="card" data-status="processed">
    A card already processed
</div>
--card-status: attr(data-status type(<custom-ident>));

.card {
    color: if(
      style(--card-status: pending): darkgray;
      else: black;
    );
}

Da die if()-Funktion nach dem aktuellen Modell immer nur den Wert einer Property setzen kann, eignet sie sich nicht für umfangreichere Verzweigungen, die mehrere Properties umfassen. Hier dürfte aber das “klassische Modell” mit unterschiedlichen Klassen ohnehin die bessere Wahl sein.