CSS :indeterminate Pseudo Classe
La pseudo-classe CSS :indeterminate sélectionne les éléments dans un état indéterminé. Découvrez-la avec des exemples pratiques.
La pseudo-classe CSS :indeterminate correspond aux contrôles de formulaire qui se trouvent dans un état indéterminé — un troisième état qui n'est ni "activé" ni "désactivé". Ce chapitre explique quels éléments peuvent entrer dans cet état, comment le déclencher et comment le styliser, avec des exemples exécutables pour les cases à cocher, les groupes de boutons radio et les barres de progression.
Signification de "indéterminé"
Certains contrôles de formulaire ont normalement deux états (coché / décoché, ou une valeur de progression connue). L'état indéterminé représente une troisième condition "indécise". La pseudo-classe :indeterminate cible trois types d'éléments :
- Cases à cocher (
<input type="checkbox">) dont la propriété DOMindeterminateest définie surtrue. C'est la classique case à cocher tri-état "certains, mais pas tous, les éléments enfants sont sélectionnés". - Boutons radio (
<input type="radio">) — chaque bouton d'un groupe portant le même nom est ciblé tant qu'aucune option de ce groupe n'est sélectionnée. - Barres de progression (
<progress>) sans attributvalue, ce qui signifie que la durée de la tâche est inconnue et que la barre s'anime sans remplissage fixe.
L'état indéterminé est défini en JavaScript, pas en CSS — il est impossible d'y entrer avec une règle CSS seule. Pour les cases à cocher, vous définissez element.indeterminate = true via JavaScript. La définition de cette propriété ne modifie pas checked ; les deux sont indépendantes. L'apparence visuelle indéterminée (généralement un tiret à la place d'une coche) et une correspondance :checked sont deux choses distinctes. Réinitialiser le formulaire avec form.reset() remet à false l'indicateur indeterminate d'une case à cocher.
La pseudo-classe :checked stylise l'état coché, tandis que :indeterminate stylise l'état indécis. Un contrôle peut être l'un, l'autre ou aucun des deux, mais jamais les deux en même temps. Vous pouvez combiner :indeterminate avec d'autres pseudo-classes telles que :hover pour styliser un élément indéterminé uniquement lorsque le pointeur se trouve dessus, ou avec :focus pour le mettre en évidence lorsqu'il reçoit le focus clavier.
Syntaxe
:indeterminate {
/* css declarations */
}Limitez le sélecteur à un type d'élément spécifique pour éviter les correspondances non souhaitées :
/* 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; }Vous pouvez également inverser la correspondance avec :not pour cibler les contrôles qui ont quitté l'état indéterminé :
/* Style a progress bar once it has a known value */
progress:not(:indeterminate) { border: 2px solid green; }Exemple : styliser une case à cocher indéterminée
Une case à cocher ne devient indéterminée que lorsque JavaScript définit la propriété indeterminate sur true. La règle CSS s'applique dès que cette propriété est définie, et s'efface dès qu'elle est remise à false. Cet exemple met en évidence le contrôle avec un box-shadow coloré.
<!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>Cas d'utilisation courant : une case à cocher tri-état "tout sélectionner"
L'application la plus pratique de :indeterminate est une case à cocher maître qui résume une liste d'options : cochée quand tous les enfants sont sélectionnés, décochée quand aucun ne l'est, et indéterminée quand certains le sont. Ce modèle est courant dans les gestionnaires de fichiers, les clients de messagerie et les tableaux de données.
La logique JavaScript maintient les propriétés indeterminate et checked de la case à cocher maître synchronisées avec les cases à cocher enfants. CSS s'occupe du reste.
<!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>Cochez l'une des cases enfants : la case à cocher "Select all" devient indéterminée et le contour vert apparaît. Cochez les trois : le contour disparaît et elle passe à l'état entièrement coché.
Exemple : un groupe de boutons radio indéterminé
Un groupe de boutons radio est dans l'état indéterminé tant qu'aucune de ses options n'est sélectionnée. La pseudo-classe :indeterminate correspond à chaque <input type="radio"> du groupe jusqu'à ce que l'utilisateur choisisse une réponse. Une fois qu'une option est choisie, l'ensemble du groupe quitte l'état indéterminé et le style est supprimé.
Cela est utile pour inciter les utilisateurs à faire un choix — par exemple, vous pouvez l'utiliser dans la validation de formulaire aux côtés de :invalid et :valid pour guider visuellement les utilisateurs vers les questions obligatoires sans réponse.
<!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>Exemple : une barre de progression indéterminée
Un élément <progress> sans attribut value n'a pas de pourcentage d'achèvement connu, il correspond donc à :indeterminate. Les navigateurs affichent par défaut une barre animée "en cours". L'ajout d'un attribut value (et éventuellement max) fait passer l'élément à l'état déterminé et la règle CSS ne s'applique plus.
<!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 propriété accent-color contrôle la couleur de remplissage de <progress> dans les navigateurs qui la prennent en charge (Chrome 93+, Firefox 92+, Safari 15.4+). Pour les navigateurs plus anciens, vous pouvez avoir besoin de pseudo-éléments préfixés par le fournisseur tels que ::-webkit-progress-bar et ::-moz-progress-bar, mais ceux-ci ne font pas partie de la spécification CSS standard.
Combinaison avec d'autres pseudo-classes
:indeterminate peut être enchaîné avec d'autres pseudo-classes d'état pour construire des sélecteurs précis :
/* 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;
}Consultez :focus, :disabled et :enabled pour plus de détails sur ces pseudo-classes.
Accessibilité
L'indicateur indéterminé est purement visuel au niveau CSS ; il ne modifie pas la valeur soumise avec le formulaire. Une case à cocher tri-état est toujours soumise comme cochée ou décochée, selon l'état checked actuel.
Pour les technologies d'assistance, vous devez exposer explicitement le troisième état en utilisant l'attribut aria-checked="mixed" sur le contrôle maître. Sans cela, les lecteurs d'écran annoncent le contrôle comme simplement coché ou décoché, et les utilisateurs qui dépendent des technologies d'assistance ne connaîtront pas la signification de la sélection partielle.
<!-- Accessible tri-state master checkbox -->
<input
type="checkbox"
id="all"
aria-checked="mixed"
aria-label="Select all items"
/>Maintenez aria-checked synchronisé avec la propriété indeterminate dans votre 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");
}
}Pour les groupes de boutons radio :required où aucune option n'a été choisie, envisagez également d'utiliser aria-required="true" sur chaque input afin que la technologie d'assistance puisse identifier le groupe sans réponse.
Compatibilité navigateur
La pseudo-classe :indeterminate est prise en charge par tous les navigateurs modernes (Chrome, Edge, Firefox, Safari). Les trois types d'éléments — cases à cocher, groupes de boutons radio et barres de progression — sont reconnus dans les versions actuelles des navigateurs.
| Élément | Remarques |
|---|---|
input[type="checkbox"]:indeterminate | Pris en charge par tous les navigateurs modernes. Nécessite JavaScript pour définir la propriété indeterminate. |
input[type="radio"]:indeterminate | Pris en charge par tous les navigateurs modernes. S'applique automatiquement jusqu'à ce que l'utilisateur sélectionne une option. |
progress:indeterminate | Pris en charge par tous les navigateurs modernes. S'applique automatiquement lorsque l'attribut value est absent. |