This post is also avalaible in : English

Ces derniers temps je passe un peu de temps sur la recherche autour des éléments de formulaire. Vous savez certainement que historiquement il n’est pas toujours possible de personnaliser l’aspect de contrôles de formulaire pour des raisons d’accessibilité (m’a-t-on dit). Cependant il est vrai que l’apparence très variable de ces éléments est sujet à controverse. Et ce n’est pas un mal.

Les codes et styles CSS que je vais vous proposer ici utilisent le niveau 3 de CSS, par conséquent les vieux navigateurs ne sont pas concernés.
Cependant nous tâcherons de travailler nos styles (notamment les sélecteurs CSS) pour faire en sorte que ces vieilleries continuent à afficher les contrôles classiques (nos bons vieux boutons radio et cases à cocher).

Pourquoi styler les checkbox et bouton radio avec CSS ?

Pour harmoniser les styles entre les navigateurs, bien sûr, mais également pour rendre (peut-être) plus affordants certains contrôles, dans un contexte bien précis. Pour améliorer l’accessibilité dans un contexte « touch ». Les zones touchable pour les checkboxes et boutons radio sont bien trop souvent trop petites.

De même, le contraste de couleurs est par défaut très pauvre sur Mac, par exemple. Je ne comprends même pas comment ils peuvent être si mal designé.

Peut-être que votre propre objectif est différent, donc je ne vais pas m’attarder davantage sur les raisons, et sauter aux solutions techniques.

Modifier légèrement l’aspect des checkboxes

Avec cet exemple, nous allons poser la base de notre CSS, cela me permettra de vous expliquer précisément les sélecteurs utilisés.
Voici ce que je souhaite obtenir.

Non stylées (gauche) VS stylées (droite)

Voir la démonstration

HTML – Quelques bases

Mais commençons par notre code HTML, que je vais proposer uniquement sous forme de quelques paragraphes avec un label et un input dans chacun d’eux.

<p id="label">Do you like?</p>
<p>
	<input type="checkbox" id="test1" />
	<label for="test1" aria-describedby="label">Red</label>
</p>
<p>
	<input type="checkbox" id="test2" checked="checked" />
	<label for="test2" aria-describedby="label">Green</label>
</p>
<p>
	<input type="checkbox" id="test3" disabled />
	<label for="test3" aria-describedby="label">Blue</label>
</p>
<p>
	<input type="checkbox" id="test4"  checked="checked" disabled />
	<label for="test4" aria-describedby="label">White</label>
</p>

Ce code propose dans l’ordre une checkbox classique, une cochée, une désactivée, et une désactivée cochée.

Gardez en tête l’importance des attributs ID et FOR. Vous devez relier le label et la checkbox ensemble grâce à ces attributes, en leur donnant la même valeur. C’est obligatoire pour des raisons d’accessibility, mais aussi pour que le code qui suit fonctionne.

Le code CSS pour ces checkboxes personnalisées

Dans l’absolu, l’élément input:checkbox n’est pas stylable. Nous allons donc jouer sur les styles du label, notamment ses deux pseudo-éléments que nous allons créer et manipuler.

form p {
	/* permet de positionner la checkbox */
	position: relative;
}

[type="checkbox"]:not(:checked), 
[type="checkbox"]:checked {
	/* Cache la checkbox sans
	   la rendre invisible aux
	   lecteurs d'écran */
	position: absolute;
	left: 0;
	opacity: 0.01;
}

/* Preparer le label */
[type="checkbox"]:not(:checked) + label,
[type="checkbox"]:checked + label {
	position: relative; /* permet de positionner la checkbox */
	padding-left: 2.3em; /* place pour la box */
	font-size: 1.05em;
	line-height: 1.7;
	cursor: pointer; 
}
La version rétro-compatible

 

C’est dans ce début que réside l’astuce du « j’affiche du personnalisé pour les navigateurs récents, et du classique pour les navigateurs plus vieux ». Si vous n’avez pas besoin du support navigateur pour IE 11, vous pouvez utiliser cette version :

form p {
	position: relative;
}

[type="checkbox"] {
	position: absolute;
	left: 0;
	opacity: 0.01;
}

[type="checkbox"] + label {
	position: relative;
	padding-left: 2.3em;
	font-size: 1.05em;
	line-height: 1.7;
	cursor: pointer; 
}
Version plus simple

Un peu d’explication du code : La première déclaration permet de placer la checkbox sous la checkbox que nous allons créer visuallement tout en conservant sa lisibilité par les lecteurs d’écran. La planquer visuellement sans utiliser de display:none; qui lui casse la lisibilité.

La seconde déclaration permet de rendre le label plus « affordant » et de faire une petite place pour notre future checkbox.
La position relative nous est utile pour positionner précisément la checkbox à venir (le label devient référant).

Ne cibler que les navigateurs récents

En effet, tous nos styles personnalisés vont commencer par : [type="checkbox"]:checked ou [type="checkbox"]:not(:checked), ce qui veut dire que si le navigateur ne reconnait pas le sélecteur, ces styles ne seront pas appliqués. C’est une sorte de détection de support du navigateur 🙂

Si vous n’avez pas besoin du support IE 11, utilisez la seconde syntaxe fournie ci-dessus.

Création des checkboxes

Maintenant nous allons visuellement la checkbox grâce aux pseudo-éléments :after (on l’utilisera pour la coche en forme de croix) et :before (on l’utilisera pour la case à cocher).

/* Aspect de la case */
[type="checkbox"]:not(:checked) + label::before,
[type="checkbox"]:checked + label::before {
	content: '';
	position: absolute;
	left: 0;
	top: 0;
	width: 1.4em;
	height: 1.4em;
	border: 1px solid #aaa;
	background: #FFF;
	border-radius: .2em;
	box-shadow: inset 0 1px 3px rgba(0,0,0, .1), 0 0 0 rgba(203, 34, 237, .2);
	transition: all .275s;
}

/* Aspect de la coche */
[type="checkbox"]:not(:checked) + label::after,
[type="checkbox"]:checked + label::after {
	content: '✕';
	speak: never; /* Pour être sûr que le lecteur d'écran ne lira pas "fois" */
	position: absolute;
	top: .38em;
	left: .18em;
	font-size: 1.6em;
	color: #CB22ED;
	line-height: 0;
	transition: all .2s; /* Petite transition */
}

/* Aspect non cochée */
[type="checkbox"]:not(:checked) + label::after {
	opacity: 0;
	transform: scale(0) rotate(45deg);
}

/* Aspect cochée */
[type="checkbox"]:checked + label::after {
	opacity: 1;
	transform: scale(1) rotate(0);
}
La CSS pour les checkboxes personnalisées

La première déclaration ici permet de régler la taille de la coche, sa position, sa couleur, etc.

Les deux suivantes permettent de définir leur forme : non cochée est transparent et réduit, cochée est opaque et à l’échelle. Ces valeurs vont subir une transition de 0 vers 1 (ou inversement), puisqu’on a prévu une animation avec la propriété transition.

Styler les différents états

Nos styles de base sont en place, maintenant si vous souhaitez régler les autres états (désactivée, désactivée et cochée, qui a le focus) voici quelques proposition de style, principalement des modifications sur l’aspect focus ou de la coche (couleur, forme).

/* Disabled checkbox */
[type="checkbox"]:disabled:not(:checked) + label::before,
[type="checkbox"]:disabled:checked + label::before {
	box-shadow: none;
	border-color: #bbb;
	background-color: #e9e9e9;
}

/* Disabled checked */
[type="checkbox"]:disabled:checked + label::after {
	color: #777;
}

[type="checkbox"]:disabled + label {
	color: #aaa;
}

/* Accessibility focus */
[type="checkbox"]:checked:focus + label::before,
[type="checkbox"]:not(:checked):focus + label::before {
	box-shadow: inset 0 1px 3px rgba(0,0,0, .1), 0 0 0 6px rgba(203, 34, 237, .2);
}

Voilà pour quelques idées de styles personnalisés.

N’oubliez pas de préfixer les propriétés CSS3 pour les navigateurs concernés, si vous avez encore besoin de les supporter.

Poussons le délire un peu plus loin – Styles avancés

Je ne vais pas faire le détail de cette démonstration pour la simple et bonne raison que tout le principe reste le même.
Il est possible ensuite de composer autant d’éléments visuels en ajoutant éventuellement des éléments HTML dans le label (essayez de ne pas en abuser quand même).
Voici donc ce qu’il est possible de faire avec un élément supplémentaire dans le label.

checkbox-flat-ui

Voir la démonstration

Ces deux exemples de styles personnalisés utilisent l’unité em pour le premier et pixel (px) pour plus d’aisance à leur compréhension dans ce deuxième cas. Pour faire les choses correctement et de manière plus flexible, essayez d’utiliser l’unité em, % ou rem suivant votre besoin et expérience.

À la recherche d’idées

Une fois que j’avais réussi à faire ça, tout content de moi je suis allez voir ce que font les copains.
Voici quelques idées, plus graphiques que techniques, car la plupart des démonstrations que j’ai vu ne sont pas accessibles.

Checkbox animée
Checkboxes Animées

checkbox-lightsaber
Checkboxes sabres laser

checkbox-styles
Diverses checkboxes

Et ceux qui ont bien compris le principe, j’imagine que vous comprenez aussi que l’on peut produire ce genre de styles avec des boutons radio ?

Quelques articles pour aller plus loin

Si vous ne le saviez pas, vous pouvez également styler certains éléments de formulaire comme les  les input de type file, ou même l’élément progress en HTML5.

Bon, ben c’est à vous maintenant !