Le problème du jour, c'est mon menu de navigation principal sur mobile. En effet, depuis que j'ai essayé d'intégrer le nom du site dans mon header, le menu ne rentre plus sur mobile.
Plusieurs questions se pose à ce stade :
- dois-je faire dans mon menu une entrée "Accueil" en plus du nom/logo du site ? Ou puis-je simplement faire comme ces sites qui intègrent le lien vers la page d'accueil dans leur logo (et donc en-dehors de la navigation) ?
- Est-ce que j'essaye d'ête malin et de faire un seul HTML, qui passe de burger menu en mobile à un menu "à plat" sur desktop ? Ou est-ce que je joue la sécurité et fait deux menus, que je masque en fonction du viewport
- Est-ce que j'utilise une icône "burger" ou est-ce que j'écris simplement "Menu" ?
- Si je change mon icône "burger" en croix, est-ce que je dois restituer cette icône (et son changement) aux utilisateurs et utilisatrices de lecteurs d'écrans.
Structure de mon header
Je n'ai pas trouvé de réponse définitive, mais j'ai l'impression qu'avoir un lien vers la page d’accueil sur le logo du site, en dehors du menu est une convention bien établie. J'ai cherché de potentielles dénonciations de cette convention mais il semble que ce soit un schéma accepté.
Je place donc dans mon header :
- Des liens d'évitements
- Le logo de mon site, avec un lien vers la page d’accueil
- Mon menu de navigation
Intégration du menu : malin ou prudent ?
Sur mobile pour réussir à tout faire rentrer, sans avoir un header qui occupe toute la moitié haute de l'écran, il faut que je le masque (avec un bouton pour l'afficher au besoin, le classique "Menu Burger"). Mais sur desktop au contraire, vu l'espace disponible, il serait criminel de ne pas l'exposer à plat.
Pour pouvoir gérer ces deux affichages (et surtout ces deux comportements), plusieurs approches sont possibles :
- Coder deux menu et les masquer/révéler en fonction de la résolution
- Coder un seul menu et lui apporter d'importantes modifications en javascript (manipulation du DOM) en fonction de la résolution de l'écran
😩 Une approche bien galère ! - Coder un seul menu et faire varier son affichage uniquement avec le CSS
Probablement l'approche la plus maline, mais aussi probablement celle avec le plus de risque d'introduire des problèmes d'accessibilité.
Avertissement
Du JS dans tous les cas
Quelque soit l'option envisagée, du javascript sera nécessaire pour afficher/masquer le menu au clique sur le bouton "menu". (Non, on utilise pas les balises <details><summary> pour simuler ce comportement ! C'est pas fait pour ça !(S'ouvre dans un nouvelle fenêtre))
Je décide de tenter la troisième approche, mais en faisant quelques recherches d'abord…
Mes lectures m'amènent jusqu'à cet article d'Adrian Roselli(S'ouvre dans un nouvelle fenêtre) puis à cette recommandation postée dans le guide de bonnes pratiques de la W3C : Example Disclosure Navigation Menu(Opens in a new window)
En reprenant la classe développée pour cette recommandation (qui a le mérite de prendre en compte toutes les interactions claviers) et en l'adaptant quelque peu à mes besoins (ici, pas de multiples menu déroulant, juste un menu burger), je peux ainsi tenter une approche maline et avec peu de HTML à moindres risques.
L'un des avantages avec l'approche du guide bonnes pratiques, c'est que le contenu de mon menu n'est pas dans le bouton menu, je peux donc masquer ce bouton et garder affiché le menu lui-même, dès que je passe sur un écran plus large :
@include phablet {
body>header {
button[aria-controls="main-menu"] {
display: none;
}
#main-menu {
display: flex;
position: relative;
border: none;
width: unset;
margin: 0;
padding: 0;
}
}
}
Je dois juste ajouter un peu de code sur mon menu pour le "ramener" dans le header (par défaut, sur mobile, il est en positionnement absolu sous le header)
Astuce
Éviter les suffixes !important
Le script trouvé dans l'exemple de la W3C injecte du style inline pour afficher/masquer le menu. Afin d'éviter d'avoir à ajouter des suffixes !important en stylant mon menu, j'ai modifier la fonction toggleMenu pour appliquer/retirer une classe hide
toggleMenu(domNode, show) {
if (domNode) {
// domNode.style.display = show ? 'block' : 'none';
if (show) {
domNode.classList.remove("hide")
} else {
domNode.classList.add("hide")
}
}
}
PS : cette fonction toggleMenu n'est d'ailleurs pas très bien nommée, vu que celle-ci ne bascule pas le menu d'un état à l'autre mais plutôt lui assigne un état "affiché" ou "pas affiché"
Compréhension de l'interface
Pour gagner de la place, il est tentant de remplacer le libellé de mon menu par le conventionnel logo "burger". Mais est-ce que cette icône est vraiment universellement reconnue ?
D'après cet article publié sur le site du Nielsen & Norman Group (un célèbre cabinet de recherche UX), c'est bien le cas aujourd'hui : The Hamburger-Menu Icon Today: Is it Recognizable?(S'ouvre dans un nouvelle fenêtre)
Néanmoins il y a toujours des personnes qui peuvent avoir du mal a associer cette icône au sens que nous lui donnions et, comme je ne manque pas à ce point de place dans mon header, je choisi de suivre leurs conseils et conserver le libellé.
Ceinture, brettelle … et justaucorps ! Là au moins je suis sûr que personne ne pourra louper mon menu.
Restituer les icônes et leur changement d'état ?
J'ai ajouté une petite fioriture en transformant mon icône "menu burger" en une icône "croix de fermeture".
J'ai fait cela :
- Parce que des amis ont insisté très fortement pour que je le fasse
- Parce que ça a aussi le mérite d'informer les utilisateurs et utilisatrices qui ne serait pas familier du fonctionnement d'un menu burger sur la possibilité de refermer le menu en cliquant à nouveau sur le bouton.
Maintenant se pose la question : dois-je restituer ces icônes (et leur changement) aux lecteurs d'écrans ?
Après y avoir bien réfléchi, je pense que non. L'objectif ici est de garantir la parité d'information, quelque soit le mode de consultation. Et il se trouve que les utilisateurices de lecteurs d'écrans ont déjà une information similaire qui leur est retransmise via l'attribut aria-expanded.
En fait, ajouter la restitution de ces icônes aurait plutôt comme effet d'ajouter du bruit avec des restitutions inutiles (j'imagine que les utilisateurices de lecteurs d'écrans se contrefichent que j'ai ajouté une petite animation pour passer du burger à la croix).
Astuce
Animations et cybercinétose
Bien entendu, j'ai limité l'affichage de cette animation aux utilisateurices n'ayant pas activé d'options "réduction des animations" :
@media (prefers-reduced-motion: no-preference) {
.burger-icon::before,
.burger-icon::after {
transition: all .5s;
}
}