Des cases à cocher au design personnalisé ET vraiment accessibles

Le , par Aurélien Levy - Accessibilité

Avertissement : cet article a été publié en 2014. Son contenu n'est peut-être plus d'actualité.

Nos amis designers sont friands de la personnalisation des éléments de formulaires et en particulier des cases à cocher. Il s’agit de mettre en place un design personnalisé sur des cases à cocher, au lieu du design natif des cases à cocher qui s’affiche dans les navigateurs. En tant qu’expert accessibilité je ne rentrerai pas dans le débat de l’intérêt de la chose, mon objectif est de faire en sorte que cette personnalisation ne se fasse pas au détriment de l’accessibilité. Surtout je ne veux plus être obligé de devoir répondre « non ce n’est pas possible », car comme vous allez le voir…c’est possible.

Pour les feignants de la lecture vous pouvez directement aller consulter la démo.

Être accessible cela suppose plusieurs choses :

  1. être utilisable avec les lecteurs d’écrans
  2. être utilisable sans javascript ou css
  3. être utilisable au clavier et avoir le focus clavier soit visible (et en cadeau bonus gérer l’absence d’images ou d’image de fond)
  4. être utilisable lors d’un zoom typo à 200 %

Nous allons donc voir comment atteindre cet objectif mais avant de rentrer dans les détails posons également le cadre :

  • n’étant pas un développeur, le code qui suivra n’est sans doute pas optimisé au mieux en terme de performance ;
  • je suis parti sur un support à partir d’IE8 et jquery 1.10 ;
  • il s’agit d’un proof of concept et sans doute pas de quelque-chose à copier coller tel quel ;
  • le but est d’avoir une image qui change en fonction de l’état coché ou non de la case à la place de la case à cocher classique.

Être utilisable avec les lecteurs d’écran

Sémantique, sémantique, sémantique, on ne va pas révolutionner ce qui existe déjà et qui fonctionne très bien à savoir les éléments label et input. Si vous vous attendiez à une solution à base de span cliquable patché à coup d’ARIA juste pour le plaisir de faire tendance, passez votre chemin. Nous avons également entouré nos cases à cocher d’une div class « faux_checkbox » afin de pouvoir se garder la possibilité d’avoir des cases à cocher natives dans certains cas.


<div class="faux\_checkbox">
   <label for="pommes"><input id="pommes" type="checkbox" /> Pommes</label>
   <label for="poires"><input id="poires" type="checkbox" /> Poires</label>
</div>

Être utilisable sans javascript ou css

Pour cela rien de plus simple, il suffit d’ajouter une class sur le body via javascript au chargement de la page. Ici nous ajouterons donc les class « withjs_faux_checkbox » sur le body par l’instruction :

$("body").addClass("withjs\_faux\_checkbox");

A partir de là, il suffit de préfixer tous nos sélecteurs css avec cette classe pour que la mise en forme ne soit faite que si javascript est présent :

.withjs\_faux\_checkbox .faux\_checkbox label{
    	display:block;
    	position:relative;
    	padding:10px 0px;
}

De même, pour ne pas se retrouver avec des gestionnaires d’événements qui s’appliquent alors que css est désactivé, nous utiliserons donc le même sélecteur pour cibler les éléments en javascript :

$(".withjs\_faux\_checkbox .faux\_checkbox");

Être utilisable au clavier et avoir le focus visible

Les éléments input sont nativement utilisables au clavier, nous allons donc nous appuyer sur cela pour rendre les fausses cases à cocher utilisables au clavier. Pour cela, il est donc nécessaire de NE PAS UTILISER de display none ou visibility hidden pour masquer les input car cela les rendrait inatteignables au clavier et non lisibles pour les lecteurs d’écrans. Nous pourrions donc :

  • les déplacer en dehors de l’écran avec une class type .element-invisible et ne laisser afficher que nos fausses cases mais dès lors la prise de focus ne serait plus visible (sauf à remettre la case à cocher dans l’écran ce qui graphiquement nuirait à notre volonté d’avoir des cases à cocher personnalisées).
  • Utiliser opacity:0 mais le problème serait identique.

Comment donc faire pour que notre case à cocher native soit masquée par la fausse case tout gardant la possibilité de voir le focus. Et bien, nous allons tout simplement positionner par dessus la case à cocher native notre fausse case à cocher et rendre le focus visible sur le label englobant lors de la prise du focus.

Pour cela nous avions ajouté un position:relative sur .withjs_faux_checkbox .faux_checkbox label. Il nous reste donc à générer une zone par dessus notre label en positionnement absolu avec une image de fond :

.withjs\_faux\_checkbox .faux\_checkbox label:after{
	display:block;		
	position:absolute;		
	content:" ";
	width:25px;
	height:25px;
	background:transparent url("case-neutre.png") scroll no-repeat top left;
	top:8px;
	left:0px;
	overflow:hidden;
}

L’absence d’utilisation d’image en dur dans le code nous évitera de faire des acrobaties pour les masquer au lecteur d’écran tout en nécessitant un alt non vide nécessaire pour apparaître à l’écran en cas de désactivation des images.

Cette solution présente également l’avantage d’être fonctionnelle lorsque les images sont désactivées puisqu’en cas de désactivation des images la zone par dessus se retrouvera transparente et laissera apparaître la case à cocher native. En effet, l’utilisateur peut désactiver les images mais également désactiver les couleurs ce qui a pour effet de supprimer toutes les images de fond. Il peut également avoir utilisé une css personnalisée ou activé le mode « fort contraste » de son système d’exploitation ayant le même effet.

Nous allons maintenant ajouter une class rendant visible le focus clavier lorsque l’input prend le focus :

.withjs\_faux\_checkbox .faux\_checkbox label.on{
	outline:1px dotted grey;
}

et le javascript gérant l’ajout / retrait de cette class en fonction de la présence du focus sur les input :

$(".withjs\_faux\_checkbox .faux\_checkbox input").focus(function() {
	$( this ).parents("label").addClass( "on" );
});
$(".withjs\_faux\_checkbox .faux\_checkbox input").blur(function(){
	$( this ).parents("label").removeClass( "on");
});

Il nous reste plus qu’une chose mais d’importance, que le clic sur le label ou l’activation au clavier change l’image de notre fausse case pour faire apparaître l’image de notre case dans un état coché. Pour cela, il suffit d’appliquer / supprimer une class « checked » permettant d’afficher l’autre image de fond lorsque que l’état de l’input change :

.withjs\_faux\_checkbox .faux\_checkbox label.checked:after{
	background:transparent url("case-cochee.png") scroll no-repeat top left;
}

(à noter on pourrait également le faire avec une seule image contenant les deux état et en déplaçant simplement le background-position de l’image)

et le javascript :

$(".withjs\_faux\_checkbox .faux\_checkbox input").on('change', function() {
	$(this).parents("label").toggleClass("checked");
});

Nous avons donc désormais nos fausses cases à la place de vrais, lisibles par un lecteur d’écran, utilisables au clavier, avec un focus visible et une gestion de la désactivation des css, de javascript .

Etre utilisable lors d’un zoom typo à 200 %

Pour terminer, il faut donc que les fausses cases restent masquées lorsque l’utilisateur agrandit la taille du texte à 200 % pour ne pas se retrouver avec les vraies et les fausses cases affichées ensembles. Pour cela, c’est simple, il suffit de modifier l’alignement vertical de l’inputs pour être sûr qu’il restera en haut du bloc de texte constitué par le label :

.withjs\_faux\_checkbox .faux\_checkbox input[type="checkbox"]{
	vertical-align:top;
}

Et voilà ! et comme vous avez eu le courage d’arriver jusque là, vous pouvez voir le résultat.