Case à cocher
Éléments de formulaire permettant la sélection d'une ou plusieurs options, personnalisés en pur CSS.
1. Démonstration
2. Accessibilité (Sémantique et Clavier)
Utiliser les éléments natifs permet aux lecteurs d'écran et à la navigation au clavier de fonctionner parfaitement sans aucun JavaScript.
| Élément / Interaction | Explication |
|---|---|
<fieldset> et <legend> |
Crucial : Regroupe les options entre elles. Le <legend> agit comme la « question » globale et est annoncé par le lecteur d'écran avant chaque option. |
<label> englobant |
Envelopper l'<input> dans le <label> augmente la zone cliquable (on peut cliquer sur le texte) et associe implicitement le texte à la case.
|
| Cases à cocher (Clavier) | On utilise la touche Espace pour cocher/décocher. On navigue de l'une à l'autre avec Tab. |
| Boutons radio (Clavier) | On navigue à l'intérieur du groupe avec les Flèches directionnelles (Haut/Bas/Gauche/Droite), ce qui sélectionne automatiquement l'option. On sort du groupe avec Tab. |
3. Code source
HTML
La structure sémantique parfaite pour un groupe de contrôles.
<fieldset>
<legend>Choisissez vos options :</legend>
<div class="choice-group">
<label>
<input type="checkbox" name="options" value="1">
Option 1
</label>
<label>
<input type="checkbox" name="options" value="2" checked>
Option 2
</label>
</div>
</fieldset>
CSS
Il utilise la propriété appearance: none pour effacer le style du navigateur, et recrée une case à cocher personnalisée grâce aux pseudo-éléments ::before (pour dessiner une encoche purement en CSS, sans charger de SVG externe !).
Pour créer l'encoche (« ✓ » de validation) dans la case à cocher, la méthode traditionnelle est de charger un SVG ou une image de fond. Ici, j'ai utilisé une astuce extrêmement performante : le clip-path.
On crée un carré avec la couleur du fond (var(--bg-color)), et on « découpe » ce carré en forme d'encoche grâce au clip-path.
Avantage Écologique : Zéro requête réseau, zéro base64 encombrant dans le CSS.
.choice-group {
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
}
.choice-group label {
display: flex;
align-items: center;
gap: 0.6rem;
cursor: pointer;
font-weight: 700;
}
/* Boutons radio personnalisés et accessibles */
.choice-group input[type="radio"] {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border: 2px solid var(--border-color);
border-radius: 50%;
background-color: transparent;
margin: 0;
cursor: pointer;
display: grid;
place-content: center;
}
.choice-group input[type="radio"]::before {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
transform: scale(0);
transition: 120ms transform ease-in-out;
background-color: var(--text-color);
}
.choice-group input[type="radio"]:checked::before {
transform: scale(1);
}
/* Boutons checkbox personnalisés et accessibles */
input[type="checkbox"] {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border: 2px solid var(--border-color);
border-radius: 10%;
background-color: transparent;
margin: 0;
cursor: pointer;
display: grid;
place-content: center;
}
input[type="checkbox"]::before {
content: "";
width: 10px;
height: 10px;
border-radius: 10%;
transform: scale(0);
transition: 120ms transform ease-in-out;
background-color: var(--text-color);
/* L'encoche en pur CSS (Éco-conception : 0 octet réseau) */
box-shadow: inset 1em 1em var(--bg-color);
transform-origin: bottom left;
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
input[type="checkbox"]:checked::before {
transform: scale(1);
}
input[type="checkbox"]:checked {
background-color: var(--text-color);
}
input[type="checkbox"]:checked::before {
transform: scale(1);
}