Les techniques de navigation mobile en CSS
Résumé de l'article, pour les pressés : CSS offre des moyens de déployer des menus de navigation sur mobile sans nécessiter de requêtes et traitements JavaScript. Mais en contrepartie, les inconvénients sont souvent nombreux (bidouilles, compatibilité). au final, JavaScript a encore de beaux jours devant lui.
Une page regroupant ces différentes techniques est visible à l'adresse http://goetter.fr/nav/
Pascal Cauhepe a eu la bonne idée de me proposer une discussion au sujet des menus de navigation en pur CSS sur Branch.com. J'ai pensé qu'il serait utile d'en partager publiquement mes élucubrations, afin d'obtenir des avis, suggestions et idées extérieures.
On va commencer par les généralités, et un premier "inconvénient" inhérent au choix de CSS par rapport à JavaScript : un menu déroulant implique une notion de comportement. Or le langage destiné à gérer le comportement est JS et non CSS.
Second inconvénient commun à toutes les navigations CSS : la compatibilité. Quelle que soit la solution choisie, elle sera moins compatible qu'un équivalent en JavaScript… dès lors que le navigateur mobile a activé JS.
Je vais à présent passer rapidement en revue les différentes solutions CSS à disposition pour cibler un événement (j'en oublie peut-être) et susceptibles d'être employées pour une navigation:
simple à mettre en place, pas de bidouilles ni de code HTML inutile, à part un onclick="" pour certains navigateurs (Firefox mobile, Opera mini)
pas de requête et traitement JS nécessaire
ne correspond pas au même événement sur desktop (survol) et sur mobile (touch)
on ne peut pas refermer simplement le menu
pas de navigation possible au clavier
ciblage limité en CSS (on ne peut avoir d'action que sur un frère ou un enfant)
Un exemple de menu avec CSS :hover
compatibilité relativement importante
simple à mettre en place, quelques bidouilles HTML (onclick="" pour certains navigateurs, et tabindex="0" pour prendre le focus)
correspond au même événement sur desktop (clic) et sur mobile (touch / clic)
pas de requête et traitement JS nécessaire
pas reconnu par anciens smartphones (ex. Android 2.1 et 2.3)
on ne peut pas refermer simplement le menu sur mobile
pas de navigation possible au clavier
ne permet pas plusieurs sous-niveaux de menu
ciblage limité en CSS (on ne peut avoir d'action que sur un frère ou un enfant)
Un exemple de menu avec :focus
compatibilité assez importante
correspond au même événement sur desktop (clic) et sur mobile (touch / clic)
on peut refermer simplement le menu sur mobile en recliquant sur le bouton
permet plusieurs sous-niveaux de menu
pas de requête et traitement JS nécessaire
pas reconnu par certains navigateurs (ex. Opera mobile, Opera mini, Firefox mobile)
quelques bidouilles HTML nécessaires (label et input checkbox masqués pour faire fonctionner l'événement + onclick="" pour certains navigateurs)
ciblage limité en CSS (on ne peut avoir d'action que sur un frère ou un enfant)
Un exemple de menu avec :checked
compatibilité assez importante (un peu meilleure que :checked)
correspond au même événement sur desktop (clic) et sur mobile (touch / clic)
on peut refermer simplement le menu sur mobile en recliquant sur le bouton
permet plusieurs sous-niveaux de menu
pas de requête et traitement JS nécessaire
quelques bidouilles HTML nécessaires (label et input checkbox required pour faire fonctionner l'événement + onclick="" pour certains navigateurs)
ciblage limité en CSS (on ne peut avoir d'action que sur un frère ou un enfant)
Un exemple de menu avec :valid
compatibilité assez importante
correspond au même événement sur desktop (clic) et sur mobile (touch / clic)
permet plusieurs sous-niveaux de menu
pas de bidouilles HTML nécessaires (à part un onclick="" pour certains navigateurs)
ciblage intéressant en CSS (on peut cibler n'importe quelle ancre dans la page)
pas de requête et traitement JS nécessaire
nécessite une ancre dans la page et peut générer des "sauts en haut de page"
casse l'historique de navigation (5 clics sur le menu = 5 retours en arrière nécessaires dans l'historique)
on ne peut pas refermer simplement le menu sur mobile (sauf en bidouillant à l'aide d'un 2è bouton caché)
Un exemple de menu avec :target
Et pour finir : JavaScript :)
compatibilité maximale (si JS est activé)
correspond au même événement sur desktop (clic) et sur mobile (touch / clic)
on peut refermer simplement le menu sur mobile en recliquant sur le bouton
on peut facilement cibler n'importe quel élément de la page
permet plusieurs sous-niveaux de menu
requête et traitement JS nécessaire
nécessite souvent d'implémenter des fonctionnalités / détections complémentaires qui complexifient le code initial (onresize, timeout, zoom utilisateur, etc.)
Un exemple de menu avec JavaScript