Customiser un input checkbox sans label

Avant de commencer
Première fois que vous vous attaquez à la personnalisation d'un input de type checkbox ? Je vous conseille de d'abord aller lire mon autre article :

Comme dans mon article précédant, le but de celui-ci sera de réussir à déveloper un input checkbox sans label visible avec seulement de l'HTML et du CSS tout en restant 100% accessible.

Voici le résultat final:

See the Pen
Checkbox without label
by Laura Durieux (@Lauwed)
on CodePen.

Ce tutoriel se résume à :

  1. Côté HTML et accessibilité
  2. Casser l'apparence par défaut de l'input checkbox
  3. Personnaliser l'état checked de l'input checkbox

N'attendons plus et plongeons tête la première.

Côté HTML et accessibilité

La balise form

Commençons par créer notre HTML de base. Tout d'abord, qui dit balise input, dit balise form. Peu importe l'utilité de votre input, si vous en avez un, c'est qu'il y a une notion de formulaire. Même lorsque vous faites du shopping en ligne et que vous triez les articles en fonction de leur couleurs, c'est un formulaire.

Je vais donc commencer par créer mon formulaire.

<form action="/" method="GET" class="form">
</form>

Je spécifie les deux attributs action et method qui sont importants de connaître. Vous pouvez vous réferrer à la documentation MDN pour en savoir plus. J'ajoute également une classe form pour se mettre en situation le plus possible.

Création de l'input

Ok, première étape pour une bonne accessibilité. Maintenant, nous allons ajouter l'input et son label.

<form action="/" method="GET" class="form">
  <input type="checkbox" name="todo" value="Manger un ramen" id="ramen">
  <label for="ramen"><span>Manger un ramen</span></label>
</form>

Première chose ; Arrêtez de mettre la balise input dans la balise label. C'est un bon exemple de vouloir faire un effort niveau accessibilité, mais de ne pas correctement utiliser ses outils. Vous avez également remarqué que j'ai mis le label après l'input. Heureusement, grâce à lattribut value, le screen reader ira lire directement cette information. Du coup, que le label soit avant ou après la checkbox, la personne aura l'information lorsque il arrivera sur l'input checkbox.
Mais du coup, si je ne mets pas l'input dans le label, comment je fais pour les "lier" ? C'est ici que l'attribut for rentre en jeu. Vous pouvez remarquer que l'attribut id de l'input et l'attribut for du label on la même valeur. L'attribut for du label permet d'indiquer par l'ID à quel input il appartient. Maintenant, vous pouvez cibler un input même en cliquant sur son label.

Petit plus

Pour finir l'HTML, nous allons anticiper nos besoins pour le CSS en regroupant l'input et le label dans une div et lui donner une classe en respectant la convention de nommage BEM. Ici, le block, c'est le form et l'element, c'est l'item.

<form action="/" method="GET" class="form">
  <div class="form__item">
    <input type="checkbox" value="Manger un ramen" name="ramen" id="ramen">
    <label for="ramen"><span>Manger un ramen</span></label>
  </div>
</form>

Screenshot d'une checkbox de base où il est indiqué "Manger un ramen".

Casser l'apparence par défaut de l'input checkbox

Le style par défaut et utilisation de appearance: none;

Par défault, l'apparence et l'état checkeddes inputs sont assez simples.
Screenshot de deux inputs checkbox montrant le style par défault lorsque la checkbox est checked et unchecked.

La propriété de base qui donne justement ce style par défaut, c'est appearance: auto; inclus dans la user agent stylesheet. Notre première étape sera donc de supprimer ce style par défault en enlevant l'apparence automatique en utilisant appearance: none;.

input {
    appearance: none;
}

Ajouter du style à l'input

Le résultat c'est... Rien ! Cette propriété enlève tous les styles par défault, ce qui veut dire que la checkbox n'est plus visible, car elle n'a plus de largueur, hauteur, bord, .. définis !
Très bien, maintenant nous allons parler stratégie. Le but ici, c'est de seulement avoir le visuel d'un input checkbox et ne même plus avoir de texte. La première pensée logique serait de faire dispiraître le labele et de ne changer l'apparence que de l'input. Or, ce n'est pas la bonne manière de procéder. Pourquoi ? Car comme vous allez le voir, nous allons utiliser un pseudo-element ; ::before et ce n'est pas possible de l'utiliser sur un élément de type input, car celui est une balise auto-fermante et ne permet la création de pseudo-element. Donc, au lieu de créer une 45ème balise div, nous allons utiliser la balise label sur laquelle nous pouvons faire tout ça.
Autant dans le précédent tutoriel, ça nous arrangeais pas la propriété appearance: none;, autant ici ça nous arrange. Elle nous permet de nous débarraser visuellement de la checkbox sans l'enlever du DOM, elle reste donc complètement accessible.
Une autre technique, aurait été d'enlever la propriété ... et d'appliquer ce snippet de style à l'input pour cacher cet élément visuellement, sans le détacher du DOM pour qu'il reste accessible pour les screen readers.

clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;

Pour plus d'informations, n'hésitez pas à aller sur l'article de a11y, Hide content.

Par conséquent, ce sous-titre est mensongé et je vous propose de passer au suivant.

Ajouter du style au label

Maintenant que l'input est visuellement caché, nous allons nous attaquer au label. Comme style, j'ai décidé du Neumorphism, même si cette tendance est très déconseillée car elle est très pauvre en contraste et est très peu accessible pour les gens qui ont des déficiences visuelles. Je vous conseille d'aller lire ces petits articles pour plus comprendre la problématique autant de cette tendance :

label {
    /* Important, cela nous permettra de centrer l'icône à l'intérieur. */
    position: relative;
    /* Hauteur, largeur, ... */
    height: 70px;
    width: 70px;
    padding: 20px;
    /* Permet d'être un rond */
    border-radius: 50%;
    transition: 0.3s ease;
    /* Ce qui donne l'effet neomorphique */
    box-shadow: -2px -2px 5px rgba(white, 1), 2px 2px 5px rgba(black, 0.1);
    /* Pour cacher le texte du label */
    white-space: nowrap;
    text-indent: -2000%;
    overflow: hidden;
}

Il nous manque plus qu'à ajouter l'icône au milieu du cercle. Pour cela, je vais utiliser le pseudo-élément ::before, faire en sorte qu'il fasse la taille du label et après mettre mon icône en background. Il y a des milliards de faire différentes et la mienne n'est pas forcément la meilleure. J'ai récupérer l'icône sur le super site Iconmonstr.

label::before {
    /* Important et indispensable si vous voulez que votre pseudo-élément s'affiche */
    content: "";
    width: 100%;
    height: 100%;
    background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0xOCAyNGgtMTJsLTIuNDA0LTEzLjg5OWMtLjYgMS4wODctMS4yODggMi4zMzYtMS43MDQgMy4wOTUtLjQ5Ni45MDctMS44OTIuNTUxLTEuODkyLS40OCAwLS4xNjIuMDU0LS4zMjcuMTM3LS40OC44MjgtMS41MTQgMi43MzctNC45NjMgMi44OC01LjIyMWwtLjAwMi0uMDE1aDkuOTI0bDEuNjIzLTYuMjU5Yy4xMi0uNDQ3LjUyNC0uNzQxLjk2NS0uNzQxLjY1MSAwIDEuMTM5LjYxOS45NjggMS4yNTlsLTEuNDg1IDUuNzQxaC4zOThsNC4xOTktNS41N2MuMzE3LS40NTMuOTQxLS41NjMgMS4zOTMtLjI0Ni40NTIuMzE2LjU2Mi45NDEuMjQ2IDEuMzkzbC0zLjM5NyA0LjQyM2gzLjE2NmwtLjAwNy4wMzZjLjIxMi4zODIgMi4wNTkgMy43MTggMi44NjkgNS4yLjA4My4xNTMuMTIzLjMxOC4xMjMuNDggMCAxLjAzNi0xLjM4NCAxLjM4NC0xLjg3OC40OC0uNDEzLS43NTYtMS4wOTUtMS45OTItMS42OTMtMy4wNzRsLTIuNDI5IDEzLjg3OHptLTIuNDctOGgtNy4wM2wtMi4zOTEtMy4zNDcgMS41NjUgOS4zNDdoOC42ODFsMS41NjUtOS4zNDctMi4zOSAzLjM0N3ptMi41NDItN2gtMTIuMTE0bDMuNTcxIDVoNC45NzFsMy41NzItNXptLTQuMDU3IDIuNWMwLS4yNzYtLjIyNC0uNS0uNS0uNWgtM2MtLjI3NiAwLS41LjIyNC0uNS41IDAgLjI3NS4yMjQuNS41LjVoM2MuMjc2IDAgLjUtLjIyNS41LS41Ii8+PC9zdmc+");
    background-position: center;
    background-size: 50px;
    background-repeat: no-repeat;
    /* Pour centrer l'icône */
    position: absolute;
    left: 0;
    top: 0;
    transition: background 0.3s ease;
}

Screenshot du résultat de l'apparence du label, input checkbox sans label

Personnaliser l'état checked de l'input checkbox

Nous avons le style de base de notre input. Pourtant, quand je clique sur mon "faux" bouton (car c'est un label), rien ne se passe. Il nous faut encore définir le style pour l'état :checked de l'input. faison cela sans attendre.

input:checked + label {
  outline: none;
  cursor: pointer;
  transition: 0.2s ease-in-out;
  box-shadow: inset -2px -2px 5px white, inset 2px 2px 5px rgba(0, 0, 0, 0.1);
}
input:checked + label::before {
  background-image: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0xOCAyMy45OTlsLTEyIC4wMDEtMS45ODMtMTEuNTc4LjYzNy0xLjEyMyAzLjY5MiA0LjE3MyA3LjI2NC4wMDMgMy43MjEtNC4yMTQuNjUyIDEuMTYtMS45ODMgMTEuNTc4em0tNS4wNzUtMTdsMS42MjItNi4yNThjLjEyLS40NDcuNTI0LS43NDEuOTY1LS43NDEuNjUxIDAgMS4xMzkuNjE4Ljk2OCAxLjI1OGwtMS40ODUgNS43NDFoLjM5OGw0LjIxNC01LjU3MWMuMzE3LS40NTIuOTQxLS41NjIgMS4zOTMtLjI0NS40NTIuMzE2LjU2Mi45NC4yNDYgMS4zOTJsLTMuNDEyIDQuNDI0aDMuMTY2bC0uMDA3LjAzNmMuMjEyLjM4MiAyLjA1OSAzLjcxOCAyLjg2OSA1LjIuMDgzLjE1My4xMzguMzE4LjEzOC40OCAwIDEuMDM2LTEuMzk5IDEuMzg0LTEuODkzLjQ4LS42MS0xLjExNS0xLjgwNi0zLjI3OS0yLjQ1MS00LjQ0NmwtNC42OCA1LjI1aC01Ljk2M2wtNC42NDItNS4zMjdjLS42MzQgMS4xNDYtMS44NyAzLjM4My0yLjQ5NCA0LjUyMy0uNDk1LjkwNy0xLjg3Ny41NTEtMS44NzctLjQ4IDAtLjE2Mi4wNC0uMzI3LjEyMy0uNDguODI4LTEuNTE0IDIuNzM3LTQuOTYyIDIuODgtNS4yMmwtLjAwMy0uMDE2aDkuOTI1em0xLjA3NSA0LjVjMC0uMjc2LS4yMjQtLjUtLjUtLjVoLTNjLS4yNzYgMC0uNS4yMjQtLjUuNXMuMjI0LjUuNS41aDNjLjI3NiAwIC41LS4yMjQuNS0uNSIvPjwvc3ZnPg==");
}

Screenshot du résultat de l'apparence du label lorsque l'input est checked et unchecked, input checkbox sans label

Conclusions

Félicitations !! Vous l'avez fait !
J'espère que ça vous aura aidé. J'essaye d'être la plus claire possible, mais je ne suis pas la meilleure écrivaine, donc je suis toujours ouverte aux feedbacks ouverts réspectueux.

N'hésitez pas à laisser un commentaire et de me supporter en m'achetant un café ✨

Ciao !

Leave a Reply

Your email address will not be published. Required fields are marked *

This form supports markdown. Read guide »

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.