Jemima Abu, développeuse front-end. Elle nous montre via quatre exemples comment développer des fonctionnalités poussées à l’aide de HTML et de CSS, sans recourir à l’ancienne solution en JavaScript.
Le code présenté ici a l’avantage de prendre en compte l’accessibilité et d’être compatible pour la majorité avec tous les navigateurs web !
Enfin, un tableau récapitulatif est disponible à la fin de cet article !
Le “theme switcher” consiste en un bouton “switch”, permettant de basculer entre le mode clair et le mode sombre du site. Il s’agit sous le capot d’une case à cocher, qui active le deuxième, le premier l’étant par défaut.
Pour chacun, des couleurs spécifiques vont s’appliquer au texte, aux boutons et autres éléments du site, de manière uniforme. On pourra ainsi avoir du texte blanc sur un fond noir en mode clair, et inversement en mode sombre.
La méthode consistait à détecter lorsque la case à cocher est activée, pour ajouter une classe CSS “dark” à la balise <body>, soit la balise positionnée la plus haute dans le DOM.
Ainsi, si l’on définit des variables CSS pour le texte ou la couleur de fond par défaut, celles-ci seront facilement surchargées en passant à l’autre thème.
Voici le code CSS :
body {
background-color: var(--bg-color);
color: var(--text-color);
--bg-color: #fff;
--text-color: #000;
}
body.dark {
--bg-color: #333;
--text-color: #fff;
}
Voir le Theme Switcher version JavaScript sur CodePen
On utilise ici la pseudo-classe CSS “:has”, qui applique des styles à une balise si celle-ci contient un élément spécifique. Ici, on va détecter si la balise <body> contient notre case à cocher à l’état activée, pour appliquer les couleurs du mode “sombre”.
body:has(#theme-switcher:checked) {
--bg-color: #333;
--text-color: #fff;
}
Cette méthode fonctionne sur tous les navigateurs, cependant elle ne permet pas de garder en mémoire (localStorage) le choix de l’utilisateur.
Voir le Theme Switcher version CSS sur CodePen
Un accordéon sert à afficher une grande quantité d’informations dans un espace réduit, grâce à un système de “plier / replier”. Pour cela, il se constitue de deux éléments : un bouton pour déplier ou replier un bloc de contenu, et celui-ci.
Dans les exemples suivants, nous retrouvons plusieurs accordéons ensemble, chacun correspondant à une thématique d’une foire à questions.
Ici, lorsqu’on ouvre un accordéon dans un groupe, celui qui est déjà ouvert se referme automatiquement, afin de gagner de la place sur l’écran.
De même, des éléments visuels indiquent l'ouverture ou non d’un accordéon. Pour les rendre accessibles aux personnes non voyantes et malvoyantes, qui ont recours au lecteur d’écran, des attributs ARIA sont ajoutés au code HTML. Ainsi, l’attribut “aria-expanded”, présent sur les boutons, permet de savoir si le contenu lié à ces derniers est ouvert ou fermé.
Voici le code HTML :
<div class="accordion-item">
<button class="accordion-trigger" id="accordion-trigger-1" aria-expanded="false" aria-controls="accordion-content-1">
<span class="accordion-title">Comment marche un accordéon ?</span>
<span class="accordion-icon">+</span>
</button>
<div class="accordion-content" id="accordion-content-1">
<p>Il affiche le contenu replié en fonction de l’action de l’utilisateur.</p>
</div>
</div>
Voir les accordéons version JavaScript sur CodePen
La version HTML repose sur les élément suivants :
Cette version a les avantages suivants :
Voici le code HTML :
<!-- Premier accordéon –>
<details class="accordion-item" name="accordion">
<summary class="accordion-trigger">
<span class="accordion-title">Titre 1</span>
<span class="accordion-icon" aria-hidden="true">+</span>
</summary>
<div class="accordion-content">
<!-- Contenu 1 –>
</div>
</details>
<!-- Deuxième accordéon –>
<details class="accordion-item" name="accordion">
<summary class="accordion-trigger">
<span class="accordion-title">Titre 2</span>
<span class="accordion-icon" aria-hidden="true">+</span>
</summary>
<div class="accordion-content">
<!-- Contenu 2 –>
</div>
</details>
Et le code CSS :
.accordion-item[open] .accordion-icon {
transform: rotate(45deg);
}
Voir les accordéons natifs en HTML sur CodePen
Comment animer l’accordéon, lorsqu’il passe de l’état “plié”, soit avec une hauteur à 0 pixels, à l’état “déplié”, avec une certaine hauteur ?
Historiquement, que l’animation soit faite en JavaScript ou en CSS, il faut préciser la hauteur finale du contenu à l’état déplié, pour qu’elle fonctionne. Or, la hauteur changeant selon la quantité d’éléments à afficher, elle doit souvent être calculée dynamiquement en JavaScript.
Jemina nous fait découvrir deux propriétés CSS pour pallier ce problème :
Voici le code CSS :
.accordion-content {
height: 0;
overflow: hidden;
transition: height 0.5s;
}
.accordion-item[open] .accordion-content {
height: auto;
height: calc-size(auto);
@starting-style {
height: 0;
}
}
Voir les accordéons animés en CSS sur CodePen
Une “modale”, aussi appelée “boîte de dialogue”, est une fenêtre qui apparaît au-dessus de la page Web, devant le seul contenu avec lequel il est possible d’interagir.
On a ici une modale classique, contenant du texte et un bouton de fermeture, dont l’ouverture est déclenchée par un autre bouton.
Au niveau du code HTML, on retrouve une balise <section> avec les attributs suivants pour l’accessibilité :
Note : on retrouve dans le code de Jemina un attribut aria-hidden=”true” en plus sur la balise. Celui-ci est inutile ici car un “display : none” est appliqué en CSS, le rendant invisible aux lecteurs d’écran.
Encore une fois, cette version nécessite l’ajout d’attributs ARIA au code HTML pour être accessible. De même, les comportements claviers attendus, comme fermer la modale avec la touche Echap, ou, tabuler uniquement à l’intérieur de la modale, doivent être gérés en JavaScript.
Voir la modale en JavaScript sur CodePen
Cette version repose sur trois éléments :
Pour faire le lien entre les trois, on utilise à l’API "Popover", qui met à disposition pour ce faire des attributs HTML spécifiques.
Sur la balise <div> de la modale :
Sur le bouton d’ouverture :
Enfin, sur le bouton de fermeture :
Voici le code HTML :
<button class="modal-btn" popovertarget="modal" popovertargetaction="show">Ouvrir la modale</button>
<div popover role="dialog" aria-labelledby="modal-title" class="modal" id="modal">
<div class="modal-content">
<button popovertarget="modal" popovertargetaction="hide" class="modal-close">Fermer la modale</button>
<h2 id="modal-title">Hello, React Miami! </h2>
<p>Quibusdam nulla velit dolores sed neque facere ut, tenetur fuga itaque?</p>
</div>
</div>
Ensuite, du côté du CSS, nous avons :
Les deux fonctionnent avec tous les navigateurs.
Voici le code CSS :
.modal:popover-open {
opacity: 1;
transform: scale(1);
}
@starting-style {
.modal:popover-open {
opacity: 0;
transform: scale(0);
}
}
.modal:backdrop {
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
left: 0;
}
Pour conclure, cette solution fonctionne avec tous les navigateurs et intègre des comportements clavier et souris attendus pour l’accessibilité, à savoir :
Il faut néanmoins noter qu’un comportement a été omis : lorsque la modale est ouverte, donner le focus au bouton de fermeture, soit le premier élément interactif dedans.
Note : Il existe également la balise <dialog> pour créer une boîte de dialogue native. A la place des attributs HTML vus plus haut, celle-ci utilise des événements JavaScript pour gérer l’ouverture et la fermeture de la modale. Enfin, elle intègre aussi le pseudo-élément CSS “:backdrop”, ainsi que la pseudo-classe “:open” au lieu de “:popover-oven” vu précédemment.
Voir la modale en HTML et CSS sur CodePen
Il s’agit ici de déclencher une animation selon le niveau de scroll sur la page. Jusqu’à alors, on avait recourt à des librairies JavaScript dédiées ou du JavaScript natif, qui pouvaient poser des soucis de performance et alourdir le poids des pages.
Aujourd’hui, il est possible de réaliser cela en CSS grâce à l’API “Scroll-driven animations”, compatible avec Chrome et Edge pour le moment.
Celle-ci fournit plusieurs propriétés CSS qui, appliquées à un élément, permettent d’animer celui-ci lorsqu’on le parcourt au scroll.
Voici le code HTML :
<section class="scroll-container">
<div class="scroll-element fade-in"><!-- Le bloc animé –></div>
<div class="scroll-caption">
<p>Cet élément apparaît en fondu.</p>
</div>
</section>
Et le code CSS :
@keyframes fade-in { /* On crée ici l’animation “fade-in” qui sera appliquée à l’élément */
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-in {
view-timeline-name: --fade-in-timeline; /* Nom de référence pour la “timeline” */
view-timeline-axis: block; /* Se baser sur le scroll vertical */
animation-name: fade-in; /* Fait référence à l’animation créée plus haut */
animation-timeline: --fade-in-timeline; /* Fait référence à la “timeline” définie plus haut */
animation-range: entry 25% cover 50%; /* L’animation commence lorsqu’on a scrollé 25% de l’élément, et finit lorsqu’on atteint 50% de celui-ci. */
}
Pour en apprendre davantage sur les propriétés CSS existantes et les possibilités offertes par l’API, il existe le site "Scroll-driven Animations” dédié et exhaustif.
Voir l'animation en CSS sur CodePen
Composant | Ancienne solution en JavaScript | Solution en HTML | Solution en CSS |
---|---|---|---|
Theme Switcher | Bouton “switch” permettant de basculer entre les deux thèmes | Pseudo-classe CSS “:has”, qui détecte si | |
Accordéon | Bouton ouvrant / fermant une zone de contenu | - Balises <details> et <summary> - Avec du CSS pour animer l’affichage : fonction “calc-size(auto)”, disponible sur Chrome et Edge à date, et mixin “@starting-style” | |
Modale | Balise avec un attribut role=dialog, rendue interactive | API “Popover" | |
Animation au scroll | Librairie JavaScript ou JavaScript natif | API “Scroll-driven animations”, compatible avec Chrome et Edge à date |
Via ces différents exemples, Jemima Abu nous prouve ainsi que le HTML et le CSS ont suffisamment progressé aujourd’hui, pour pouvoir intégrer des composants dynamiques sans passer par du JavaScript !
Les deux langages ne cessent d’évoluer au fil du temps, aussi une veille régulière vous évitera de réinventer la roue, avec des développements longs et inutiles sur vos projets !
Enfin, vous pouvez retrouver la conférence sur Youtube, traduite en plusieurs langues !