16 settembre 2026

CSS if() e funzioni personalizzate: logica inline e astrazione pulita nei valori

Due novità di CSS Values & Units che rendono gli stylesheet più espressivi: condizioni direttamente nei valori e funzioni riutilizzabili con argomenti.

Le nuove if() inline e le @function (funzioni personalizzate) portano in CSS un livello di “logica nei valori” e di astrazione prima possibile solo con pattern complessi o preprocessor. Vediamo sintassi, tipi di condizioni supportate, esempi pratici (media/style/supports) e come usare le funzioni per incapsulare calcoli e convenzioni di design system in modo leggibile e riutilizzabile.

Perché queste due feature cambiano davvero il modo di scrivere CSS

Negli ultimi anni CSS ha guadagnato strumenti sempre più “logici” (container queries, :has(), cascade layers). Ora arrivano due tasselli che agiscono dentro i valori delle proprietà:

  1. if(): un costrutto condizionale inline, che sceglie un valore tra più alternative.
  2. Funzioni personalizzate: definizioni riutilizzabili che accettano argomenti e restituiscono un singolo valore.

Il risultato è un CSS più compatto, più espressivo e spesso più facile da manutenere, perché riduce duplicazioni (stesso selettore ripetuto in più media query) e rende esplicite alcune convenzioni.

Nota di compatibilità: if() è disponibile in Chrome dalla versione 137.


if() in CSS: condizionali direttamente nel valore

A cosa serve

if() ti permette di scrivere una logica “a casi” direttamente in un valore:

  • invece di duplicare regole con @media / @supports / @container (style queries),
  • puoi selezionare il valore giusto in linea.

È particolarmente utile quando la differenza tra due contesti è solo un valore, non un intero blocco di dichiarazioni.

Struttura di base

La sintassi è fatta di coppie condizione → valore:

button {
  inline-size: if(
    media(pointer: fine): 30px;
    else: 44px;
  );
}
  • if( apre la funzione
  • ogni riga è condizione: valore;
  • else: è il fallback
  • ) chiude la funzione (poi c’è il ; della dichiarazione CSS)

Scriverla su più righe non è obbligatorio, ma migliora molto la leggibilità.


Le condizioni supportate: supports(), media(), style() e else

Dentro if() puoi usare tre tipi di condizioni (tutte espresse come funzioni), più else.

1) media(...)

Valuta una media query e, se corrisponde, restituisce il valore associato.

.card {
  background: if(
    media(width > 20em): red;
    else: green;
  );
}

2) supports(...)

Permette di scegliere valori in base al supporto di una feature.

.panel {
  padding: if(
    supports(selector(:has(*))): 1.25rem;
    else: 1rem;
  );
}

3) style(...): style query sull’elemento stesso

Questa è la parte più interessante: puoi interrogare lo stile dell’elemento, tipicamente una custom property, senza dover passare da un “contenitore” come succede con molte style queries.

Il pattern è: style(--nome: valore)

.task {
  background: if(
    style(--status: pending): royalblue;
    style(--status: complete): seagreen;
    else: gray;
  );
}

Qui --status è un contratto che puoi impostare in vari modi (ad esempio via classi o direttamente come custom property), e poi “switchare” valori in modo dichiarativo.

Ordine di valutazione

if() sceglie il primo ramo vero dall’alto verso il basso. Questo ti permette di:

  • mettere prima i casi più specifici
  • usare else come fallback finale

E puoi anche mixare condizioni diverse nello stesso if() (prima media(), poi style(), ecc.).


Perché if() è più pulito di molte alternative

Prima, per esprimere “stesso selettore, valori diversi” finivi spesso con:

  • duplicazione di selettori tra blocchi @media
  • hack basati su custom properties (ad esempio pattern che “accendono/spengono” fallback)
  • valori limitati a certi tipi (soprattutto lunghezze)

Con if():

  • la decisione è locale al valore
  • funziona con qualsiasi proprietà (non solo lunghezze)
  • riduce rumore e ridondanza

Funzioni personalizzate in CSS: astrazione riutilizzabile con argomenti

Cosa sono

Le funzioni personalizzate sono una via di mezzo tra:

  • una custom property (--x) che “contiene un valore”,
  • e un piccolo “modulo di calcolo” che accetta input e restituisce un solo output.

A differenza di var(--x), una funzione può:

  • prendere argomenti multipli
  • avere valori di default
  • incapsulare logica e calcoli

La definizione avviene con l’at-rule @function e un nome che, come le custom property, è un dashed-ident (quindi inizia con --).

Un esempio minimale: negare una lunghezza

Definizione:

@function --negate(--value) {
  result: calc(-1 * var(--value));
}

Uso:

.box {
  margin-top: --negate(8px);
}

Due dettagli importanti:

  • gli argomenti della funzione si leggono con var(--value)
  • la funzione restituisce il valore tramite il descrittore result:

Perché sono utili in progetti reali

Le funzioni personalizzate diventano potenti quando nascondono:

  • calcoli lunghi (calc() annidati)
  • conversioni e clamp tipici dei design system
  • formule geometriche o di animazione

In pratica: invece di “rileggere matematica” ogni volta, chi usa lo stylesheet richiama un nome intenzionale (--space(), --radius(), --fluid()…), e il CSS torna ad essere leggibile.


Come si combinano bene if() e funzioni personalizzate

Le due feature si completano:

  • if() decide quale valore usare
  • la funzione personalizzata definisce come costruire quel valore

Esempio concettuale (semplificato):

@function --tap-size(--fine, --coarse) {
  result: if(
    media(pointer: fine): var(--fine);
    else: var(--coarse);
  );
}

.icon-button {
  inline-size: --tap-size(30px, 44px);
  block-size: --tap-size(30px, 44px);
}

Qui stai trasformando una decisione ricorrente (“mouse vs touch”) in una API CSS interna al tuo progetto.


Sintesi e implicazione pratica

if() e le funzioni personalizzate spostano una parte importante della complessità:

  • dalla struttura del CSS (duplicazioni tra regole e media query)
  • al valore (dove spesso la complessità è davvero necessaria)

In termini pratici, la combo migliore è questa:

  • usa if() quando ti serve una scelta locale e leggibile tra pochi casi;
  • usa una funzione personalizzata quando quella scelta o quel calcolo si ripete e vuoi trasformarlo in un’astrazione stabile.

Il CSS diventa più compatto, ma soprattutto più “intenzionale”: meno boilerplate e più semantica nei nomi e nelle decisioni.