CSS :indeterminate Pseudo Class
La pseudo-classe CSS :indeterminate seleziona gli elementi in stato indeterminato. Leggi la spiegazione e prova gli esempi pratici.
La pseudo-classe CSS :indeterminate corrisponde ai controlli di modulo che si trovano in uno stato indeterminato — un terzo stato che non è né "attivo" né "disattivo". Questo capitolo spiega quali elementi possono entrare in quello stato, come attivarlo e come stilizzarlo, con esempi eseguibili per checkbox, gruppi di radio button e barre di avanzamento.
Cosa significa "indeterminate"
Alcuni controlli di modulo hanno normalmente due stati (selezionato / deselezionato, oppure un valore di avanzamento noto). Lo stato indeterminato rappresenta una terza condizione "indefinita". La pseudo-classe :indeterminate si applica a tre tipi di elementi:
- Checkbox (
<input type="checkbox">) la cui proprietà DOMindeterminateè impostata sutrue. Questa è la classica checkbox tri-state "alcuni, ma non tutti, gli elementi figlio sono selezionati". - Radio button (
<input type="radio">) — ogni button di un gruppo con lo stesso nome viene selezionato finché nessuna opzione in quel gruppo è selezionata. - Barre di avanzamento (
<progress>) prive dell'attributovalue, il che significa che la durata dell'operazione è sconosciuta e la barra si anima senza un riempimento fisso.
Lo stato indeterminato viene impostato in JavaScript, non in CSS — non è possibile attivarlo con una sola regola CSS. Per le checkbox si imposta element.indeterminate = true tramite JavaScript. L'impostazione di quella proprietà non modifica checked; le due sono indipendenti. L'aspetto visivo indeterminato (di solito un trattino invece di un segno di spunta) e il rilevamento da parte di :checked sono cose separate. Il ripristino del modulo con form.reset() riporta il flag indeterminate di una checkbox a false.
La pseudo-classe :checked stilizza lo stato selezionato, mentre :indeterminate stilizza lo stato indefinito. Un controllo può essere in uno, nell'altro o in nessuno dei due stati, ma mai in entrambi contemporaneamente. È possibile combinare :indeterminate con altre pseudo-classi come :hover per stilizzare un elemento indeterminato solo quando il puntatore vi si trova sopra, oppure con :focus per evidenziarlo quando riceve il focus dalla tastiera.
Sintassi
:indeterminate {
/* css declarations */
}Limita il selettore a un tipo di elemento specifico per evitare corrispondenze non volute:
/* Only checkboxes */
input[type="checkbox"]:indeterminate { outline: 2px dashed orange; }
/* Only radio buttons */
input[type="radio"]:indeterminate { opacity: 0.7; }
/* Only progress bars */
progress:indeterminate { opacity: 0.5; }È anche possibile invertire la corrispondenza con :not per puntare ai controlli che hanno abbandonato lo stato indeterminato:
/* Style a progress bar once it has a known value */
progress:not(:indeterminate) { border: 2px solid green; }Esempio: stilizzare una checkbox indeterminata
Una checkbox diventa indeterminata solo quando JavaScript imposta la proprietà indeterminate su true. La regola CSS si attiva nel momento in cui quella proprietà viene impostata e si cancella nel momento in cui viene riportata su false. Questo esempio evidenzia il controllo con un box-shadow colorato.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
input:indeterminate {
box-shadow: 0 0 2px 2px #666;
}
</style>
</head>
<body>
<h2>Indeterminate selector example</h2>
<form>
<input type="checkbox" id="box" /> Checkbox
<script>
var checkbox = document.getElementById("box");
checkbox.indeterminate = true;
</script>
</form>
</body>
</html>Caso d'uso comune: una checkbox tri-state "seleziona tutto"
L'applicazione più pratica di :indeterminate è una checkbox master che riassume un elenco di opzioni: selezionata quando tutti i figli sono scelti, deselezionata quando nessuno lo è, e indeterminata quando lo sono alcuni. Questo schema è comune nei file manager, nei client di posta elettronica e nelle tabelle di dati.
La logica JavaScript mantiene le proprietà indeterminate e checked della checkbox master sincronizzate con le checkbox figlio. CSS gestisce il resto.
<!DOCTYPE html>
<html>
<head>
<title>Tri-state checkbox</title>
<style>
/* Highlight master while in partial-selection state */
#all:indeterminate {
outline: 2px solid #8ebf42;
}
</style>
</head>
<body>
<label><input type="checkbox" id="all" /> Select all</label>
<ul>
<li><label><input type="checkbox" class="child" /> Apples</label></li>
<li><label><input type="checkbox" class="child" /> Bananas</label></li>
<li><label><input type="checkbox" class="child" /> Cherries</label></li>
</ul>
<script>
var all = document.getElementById("all");
var children = document.querySelectorAll(".child");
function syncParent() {
var checked = [...children].filter(function (c) { return c.checked; }).length;
all.checked = checked === children.length;
all.indeterminate = checked > 0 && checked < children.length;
}
all.addEventListener("change", function () {
children.forEach(function (c) { c.checked = all.checked; });
});
children.forEach(function (c) {
c.addEventListener("change", syncParent);
});
syncParent();
</script>
</body>
</html>Seleziona una delle checkbox figlio: la checkbox "Select all" diventa indeterminata e appare il contorno verde. Seleziona tutte e tre: il contorno scompare e la checkbox passa allo stato completamente selezionato.
Esempio: un gruppo di radio button indeterminato
Un gruppo di radio button si trova nello stato indeterminato finché nessuna delle sue opzioni è selezionata. La pseudo-classe :indeterminate corrisponde a ogni <input type="radio"> del gruppo finché l'utente non sceglie una risposta. Una volta selezionata un'opzione qualsiasi, l'intero gruppo esce dallo stato indeterminato e la stilizzazione viene rimossa.
Questo è utile per spingere gli utenti a fare una scelta — ad esempio, può essere utilizzato nella validazione del modulo insieme a :invalid e :valid per guidare visivamente gli utenti verso le domande obbligatorie senza risposta.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
<style>
label {
margin-right: .5em;
position: relative;
top: 1px;
}
input[type="radio"]:indeterminate + label {
color: #8ebf42;
}
</style>
</head>
<body>
<h2>:indeterminate selector example</h2>
<form>
<input type="radio" name="option" value="yes" id="yes" />
<label for="yes">Yes</label>
<input type="radio" name="option" value="no" id="no" />
<label for="no">No</label>
<input type="radio" name="option" value="dont-know" id="dont-know" />
<label for="dont-know">Don’t know</label>
</form>
</body>
</html>Esempio: una barra di avanzamento indeterminata
Un elemento <progress> privo dell'attributo value non ha una percentuale di completamento nota, quindi corrisponde a :indeterminate. I browser visualizzano di default una barra animata "in elaborazione". L'aggiunta dell'attributo value (e facoltativamente max) porta l'elemento nello stato determinato e la regola CSS non si applica più.
<!DOCTYPE html>
<html>
<head>
<title>Indeterminate progress</title>
<style>
progress:indeterminate {
opacity: 0.6;
width: 200px;
}
/* Once a value is set, show a green accent */
progress:not(:indeterminate) {
accent-color: #2a9d8f;
width: 200px;
}
</style>
</head>
<body>
<p>Indeterminate (no value): <progress></progress></p>
<p>Determinate (value set): <progress value="60" max="100"></progress></p>
</body>
</html>La proprietà accent-color controlla il colore di riempimento di <progress> nei browser che la supportano (Chrome 93+, Firefox 92+, Safari 15.4+). Per il supporto di browser più vecchi potrebbe essere necessario ricorrere a pseudo-elementi con prefisso del produttore come ::-webkit-progress-bar e ::-moz-progress-bar, che tuttavia non fanno parte della specifica CSS standard.
Combinazione con altre pseudo-classi
:indeterminate può essere concatenato con altre pseudo-classi di stato per costruire selettori precisi:
/* Indeterminate checkbox that is also focused */
input[type="checkbox"]:indeterminate:focus {
outline: 3px solid royalblue;
}
/* Indeterminate and disabled checkbox — show a muted style */
input[type="checkbox"]:indeterminate:disabled {
opacity: 0.4;
cursor: not-allowed;
}Consulta :focus, :disabled e :enabled per ulteriori dettagli su quelle pseudo-classi.
Accessibilità
Il flag indeterminato è puramente visivo a livello CSS; non modifica il valore inviato con il modulo. Una checkbox tri-state viene comunque inviata come selezionata o deselezionata, a seconda dell'attuale stato checked.
Per le tecnologie assistive, è necessario esporre il terzo stato esplicitamente tramite l'attributo aria-checked="mixed" sul controllo master. Senza di esso, gli screen reader annunciano il controllo semplicemente come selezionato o deselezionato e gli utenti che si affidano alle AT non conosceranno il significato della selezione parziale.
<!-- Accessible tri-state master checkbox -->
<input
type="checkbox"
id="all"
aria-checked="mixed"
aria-label="Select all items"
/>Mantieni aria-checked sincronizzato con la proprietà indeterminate nel tuo JavaScript:
function syncParent() {
var checked = [...children].filter(function (c) { return c.checked; }).length;
if (checked === 0) {
all.indeterminate = false;
all.checked = false;
all.setAttribute("aria-checked", "false");
} else if (checked === children.length) {
all.indeterminate = false;
all.checked = true;
all.setAttribute("aria-checked", "true");
} else {
all.indeterminate = true;
all.checked = false;
all.setAttribute("aria-checked", "mixed");
}
}Per i gruppi di radio button con :required in cui nessuna opzione è stata scelta, considera anche di utilizzare aria-required="true" su ogni input affinché le tecnologie assistive possano identificare il gruppo senza risposta.
Supporto nei browser
La pseudo-classe :indeterminate è supportata in tutti i browser moderni (Chrome, Edge, Firefox, Safari). Tutti e tre i tipi di elemento — checkbox, gruppi di radio button e barre di avanzamento — vengono riconosciuti nelle versioni attuali dei browser.
| Elemento | Note |
|---|---|
input[type="checkbox"]:indeterminate | Supportato in tutti i browser moderni. Richiede JavaScript per impostare la proprietà indeterminate. |
input[type="radio"]:indeterminate | Supportato in tutti i browser moderni. Si applica automaticamente finché l'utente non seleziona un'opzione. |
progress:indeterminate | Supportato in tutti i browser moderni. Si applica automaticamente quando l'attributo value è assente. |