Hello hello ! Le but de cet article est d'expliquer pas à pas comment customiser un input checkbox tout en gardant son label. Le plus important, c'est de réussir à jouer avec l'apparence de l'input tout en le laissant 100% accessible.
Voici l'input checkbox que nous allons réaliser dans cet article :
See the Pen
Untitled by Laura Durieux (@Lauwed)
on CodePen.
Voici les différentes étapes :
- Côté HTML et accessibilité
- Casser l'apparence par défaut de l'input checkbox
- 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>
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 checked
des inputs sont assez simples.
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
Par contre, 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 ! Il va donc falloir tout redéfinir manuellement en CSS.
Voici le style par défault de la checkbox :
input {
/* Disable default style */
appearance: none;
/* Define the width and the height */
width: 25px;
height: 25px;
/* Space between the input and the label */
margin-right: 15px;
/* Custom appearance */
border-radius: 50%;
border: 2px solid black;
}
J'ai également ajouté un peu de style à la div qui groupe le label et l'input pour qu'ils soient centrés verticalement.
.form__item {
display: flex;
align-items: center;
}
Personnaliser l'état checked
de l'input checkbox
En créant notre checkbox, nous avons fait attention à l'accessibilité, ensuite à correctement enlever le style par default et mettre le notre. Le problème suivant, c'est l'état checked
de l'input. Vu que nous utilisons appearance: none;
, lorsque vous cliquez sur l'input, il n'y a rien qui se passe visuellement. Nous allons donc devoir reprogrammer tout cela.
L'état checked
d'un input en CSS
En CSS, il est possible de cibler l'état d'un élément grâce à un pseudo-sélecteur. En fonction de la balise HTML, différents pseudo-sélecteur sont disponibles. Vous connaissez sûrement déjà hover
, focus
ou encore visited
pour les liens. Pour les inputs checkbox et radio, il existe un pseudo-sélecteur checked
. Utilisons-le de suite ;
input:checked {
background-color: #ffa726;
}
Du coup, maintenant que la checkbox est checked
, ça va donner ceci ;
Style de la checkbox checked
en utilisant les pseudo-éléments
Bon, c'est bien beau, mais c'est pas ça que nous voulons faire comme effet lorsque la checkbox est checked
. Nous aimerions qu'il y ait une boule orange qui apparaisse au centre de la checkbox. Cette boule, nous allons utiliser un pseudo-élément CSS pour la créer. Commençons pas la créer comme si elle est là par défault.
.form__item input {
appearance: none;
border-radius: 50%;
border: 2px solid black;
width: 25px;
height: 25px;
margin-right: 15px;
/* Add relative position to center the bullet to the input and not the body */
position: relative;
}
.form__item input::before {
/* Mandatory to create a pseudo element, even if the content is empty */
content: "";
/* To be able to position the bullet at the center of the input */
position: absolute;
/* Centering the bullet */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* Width and height relative to the size of the input */
width: 75%;
height: 75%;
/* Custom style */
border-radius: 50%;
background: #ffa726;
}
Maintenant, nous allons utiliser la propriété transform
pour faire apparaître la boule et la propriété transition
pour donner un effet d'animation lorsque l'input change d'état.
.form__item input::before {
/* ... */
/* Scale to 0, like that the bullet is visually hidden */
transform: translate(-50%, -50%) scale(0);
/* Transition effect on the transform property */
transition: transform .3s ease;
}
La boule devient invisible, car elle a été redimmensionnée à 0. Le pseudo-élément existe toujours, mais plus visuellement. Le but maintenant va de réussir à cibler le pseudo-élément lorsque la checkbox est checked
. Pour cela, rien de plus simple, il faut d'abord cibler l'état de l'élément parent
, puis indiquer le pseudo-élément ou psudo-sélecteur souhaité.
input:checked::before {
/* Your code here */
}
Allons-y. Voici le code besoin pour faire réapparaître la boule lorsque la checkbox est checked
.
input:checked::before {
transform: translate(-50%, -50%) scale(1);
}
Personnaliser le label d'une checkbox checked
Pour pouvoir faire cela, il faut connaître le sélecteur css +
. Ce que nous allons faire, c'est cibler le label, qui est le voisin direct de la chebox, quadn celle-ci est checked
.
input:checked + label {
color: #ffa726;
}
Style du label de la checkbox checked
en utilisant les pseudo-éléments
Comme pour la chebox, nous allons utiliser un pseudo-élément pour créer la barre qui se retrouve sur le label lorsque la checkbox est checked
. Nous allons commencer par raproduire ce style par défault, sans tenir compte de l'état de la checkbox.
Voici le style dont nous avons besoin :
.form__item label {
/* Will help to position the pseudo-element */
position: relative;
}
.form__item label span {
/* Prevent user to select the text */
user-select: none;
/* Custom style */
opacity: 0.5;
}
.form__item label::before {
/* Mandatory to create a pseudo element, even if the content is empty */
content: "";
/* To be able to position the bar at the center vertically of the label */
position: absolute;
/* Positionning the bar */
left: 0;
top: 50%;
/* Width relative to the size of the label */
width: 100%;
height: 3px;
/* Custom style */
background-color: #ffa726;
transform: translateY(-50%);
}
Comme pour la boule, nous voulons que ça soit l'état uniquement quand la checkbox est checked
. Voici les modifications que nous devons apporter au label pour son style de base :
.form__item label span {
/* ... */
/* Custom style */
opacity: 1;
/* Transition effect on the opacity */
transition: opacity .3s ease;
}
.form__item label::before {
/* ... */
/* Adding the transformation scaleX to have the horizontal appearing animation */
transform: translateY(-50%) scaleX(0);
/* The origin of the transformation. Like that the bar appears from the left to the right */
transform-origin: left center;
/* Transition effect on the transformation */
transition: transform .3s ease;
}
Je vous conseille d'aller lire un peu sur la propriété transform-origin
qui peut bien sauver des vies de temps en temps. Ensuite, nous devons ajouter un peu de style lorsque la checkbox est checked
.
.form__item input:checked + label span {
opacity: 0.5;
}
.form__item input:checked + label::before {
transform: translateY(-50%) scaleX(1);
}
Et voilà !
Merci beaucoup d'avoir lu cet article ! Je l'ai rédigé avec beaucoup de bonne humeur et j'espère avoir pu aider quelques âmes perdues.
N'hésitez pas à laisser un commentaire et de me supporter en m'achetant un café ✨
Ciao !