documents

Mode dégradé et mode rehaussé

Le mode dégradé (ou dégradation gracieuse) et le mode rehaussé (ou rehaussement progressif) sont les deux côtés d'une même pièce. Dans ce contexte, ils concourrent tous deux à rendre un site Web accessible à tout agent d'utilisateur, en procurant une esthétique et/ou une convivialité améliorées aux navigateurs capables de plus. La différence entre les deux est là où commence votre démarche.

Ici, il y a quelques temps, j'ai écrit un article intitulé Visuel contre structurel[1] décrivant deux approches très différentes de la conception graphique Web. Les notions de mode dégradé et de mode rehaussé sont étroitement liées à ces deux approches.

Le mode dégradé

Le mode dégradé est le plus ancien des deux concepts. Le terme sert également dans d'autres domaines que la conception Web, tels que les systèmes mécaniques ou électriques à tolérance de pannes.

La prémisse du mode dégradé est de construire d'abord pour les dispositifs plus récents et performants puis d'ajouter des gestionnaires pour ceux qui le sont moins. En d'autres termes, on se concentre sur le majoritaire avant de servir le minoritaire. Cette approche est assez semblable à l'approche visuelle de la conception graphique Web, où la priorité est d'offrir une belle présentation à la majorité des visiteurs.

Un exemple familier de mode dégradé est l'attribut alt des images. Correctement utilisé, il fournit un texte équivalent qui transmet l'information pareillement à l'image aux utilisateurs dans l'impossibilité de la voir. L'équivalent textuel possède très probablement une esthétique moins plaisante, une image valant mille mots, l'expérience d'utilisateur est donc légèrement dégradée.

On peut assimiler l'utilisation de tables pour la mise en pages comme une forme de mode dégradé : si le style CSS ne peut pas s'appliquer, par exemple dans le cas d'un navigateur vraiment très ancien, il reste au moins la mise en page de base. Mais ça ne fonctionne pas très bien avec les navigateurs textuels comme Lynx et certains navigateurs de téléphones mobiles qui ne gèrent pas les tables.

Une autre présence courante dans les sites construits selon le concept de mode dégradé : l'élément noscript. Vous offrez certaines fonctions fondées sur du JavaScript et vous ajoutez une version simplifiée pour les agents d'utilisateurs qui ne reconnaissent pas JavaScript ou qui l'ont désactivé. Les menus déroulants ou détachés, omniprésents, en constitueraient un exemple :

Premier exemple

<script type="text/javascript" src="/menu.js"></script>
  <noscript>
    <ul id="menu">
    <li><a href="/">Accueil</a></li>
    <li><a href="/produits/">Produits</a></li>
    <li><a href="/services/">Services</a></li>
    </ul>
  </noscript>

Une fonction JavaScript est susceptible de créer un menu où les éléments « Produits » et « Services » ont des sous-menus qui se déroulent, se détachent ou se développent lorsque le pointeur de la souris de l'utilisateur survole ces éléments principaux. L'alternative sans JavaScript offre uniquement un accès direct aux éléments principaux, tandis que les sous-menus sont inclus (vraisemblablement) dans des éléments noscript similaires dans les pages intérieures respectives.

Cette approche est conçue pour les utilisateurs majoritaires, ceux avec un navigateur graphique reconnaissant JavaScript, mais elle permet un mode dégradé qui fonctionne même avec les navigateurs textuels les plus humbles. Elle présente aussi l'avantage d'offrir des liens HTML appropriés aux agents d'utilisateurs non-JavaScript, en répondant ainsi au problème critique du traitement des menus JavaScript par les moteurs de recherche.

Il y a néanmoins un souci avec noscript. Je peux utiliser un navigateur compatible JavaScript et sur lequel l'interprétation est activée, mais un pare-feu d'entreprise intermédiaire pourrait filtrer tout code JavaScript extérieur pour des raisons de sécurité. Auquel cas, l'élément noscript ne sera pas rendu (car mon navigateur est compatible JavaScript), mais le code JavaScript qui doit créer le menu ne sera pas appliqué non plus puisqu'il est coincé derrière le pare-feu.

Une dégradation pas si gracieuse

Malheureusement, le concept de mode dégradé va parfois bien au-delà que ce qui est raisonnablement supportable dans la dégradation. Voici pour le pire :

Deuxième exemple

<script type="text/javascript" src="/menu.js"></script>
  <noscript>
    <p>Veuillez utiliser un navigateur compatible avec JavaScript.</p>
  </noscript>

C'est impardonnable pour un site Web sérieux mais acceptable pour un petit site amateur destiné aux amis et à la famille.

En tant que concepteurs ou développeurs Web, nous n'avons pas le droit de dire à nos visiteurs quels navigateurs ils « devraient » utiliser, ni « d'activer JavaScript ». Nous ne connaissons pas leurs raisons d'utiliser Lynx ou de désactiver l'interprétation des scripts de leur côté. Ils n'ont peut-être même pas la possibilité de « mettre à jour » ou « d'activer JavaScript » pour des questions de bande passante, de contraintes matérielles ou budgétaires, à cause de la politique de leur service informatique ou parce qu'ils n'utilisent même pas leur propre ordinateur.

Le mode dégradé est de loin préférable à un site complètement inaccessible pour certains utilisateurs, mais ce n'est pas la meilleure approche. Comme pour la démarche de conception visuelle, il est souvent difficile de commencer avec toutes les fonctions puis de les retirer une par une sans tout casser.

Le mode rehaussé

Le mode rehaussé est apparu au moins sous ce nom en 2003 lorsque Steve Champeon à commencer à l'employer sur Webmonkey et au cours de la conférence SXSW. Il va à l'opposé du mode dégradé : on commence d'abord par la version de base puis on apporte des améliorations pour ceux qui peuvent les exploiter. En comparant encore avec les approches conceptuelles, il s'agit du même raisonnement que pour la conception structurelle. On commence par le balisage et on ajoute le style dessus, ce qui est un rehaussement progressif en soi.

La manifestation la plus courante du mode rehaussé est probablement la feuille de style CSS externe. Les navigateurs incompatibles avec CSS l'ignorent, le navigateur prend donc seulement le balisage ordinaire qu'il rend conformément à sa feuille de style intégrée, mais les navigateurs graphiques modernes l'appliquent en améliorant ainsi l'esthétique et la convivialité pour les utilisateurs majoritaires et les utilisateurs expérimentés.

Les diverses techniques de remplacement d'images, la méthode Flash satay et AJAX (parfois) constituent d'autres exemples de mode rehaussé.

Aujourd'hui on parle plus souvent de mode rehaussé au sujet de JavaScript. Le mot-clé pour cela est JavaScript inaperçu (ou non intrusif). Un script inaperçu est silencieusement ignoré par les agents utilisateurs non compatibles mais appliqué par les appareils qui le sont. Tout comme une feuille de style externe.

Revenons sur le menu de navigation ayant servi d'exemple pour le mode dégradé. Comment le réaliser en mode rehaussé ?

Nous commencerions par le balisage en visant le plus petit dénominateur commun : HTML. Un menu de navigation est sémantiquement parlant une liste de liens. L'ordre de ces liens n'affecte pas la signification de la liste dans son ensemble, c'est donc une liste non ordonnée.

Troisième exemple

   <ul>
    <li><a href="/">Accueil</a></li>
    <li><a href="/produits/">Produits</a></li>
    <li><a href="/services/">Services</a></li>
   </ul>

Ce code fonctionnera partout de Lynx et Mosaic 1.0 jusqu'aux dernières versions d'Opera, Firefox et Safari. Googlebot et ses cousins robotiques seront ravis aussi.

L'étape suivante consiste à ajouter des améliorations pour la grande majorité des utilisateurs dont les navigateurs sont compatibles avec CSS. Nous ajoutons les règles dans un fichier CSS externe pour styler le menu. Après l'ajout d'un élément link appelant la feuille de style externe, l'aspect est bien meilleur pour la majorité des visiteurs mais cela n'a lieu en aucune façon au détriment des utilisateurs de Lynx ou de Googlebot. (Bon d'accord, il leur faudra télécharger quelques octets de plus mais ce sera négligeable même avec une connexion lente en accès commuté ou un téléphone mobile GSM).

Nous pouvons l'améliorer encore en ajoutant aux éléments principaux des sous-menus déroulants, ou détachés, ou développés en utilisant du JavaScript inaperçu. Pour réduire la quantité de code, nous commençons par assigner des attributs id aux éléments de la liste :

Quatrième exemple

	<li id="produits"><a href="/produits/">Produits</a></li>
    <li id="services"><a href="/services/">Services</a></li>

Puis nous créons un fichier JavaScript séparé avec quelques fonctions :

Cinquième exemple

 function addProducts()
  {
   // Trouver l'élément li auquel ajouter un sous-menu
   var parent = document.getElementById("produits");

   // Vérifier son existence (échouer silencieusement)
   if (parent) {

   // Créer une liste non ordonnée imbriquée
   var ul = parent.appendChild(document.createElement("UL"));

   // Ajouter les éléments de liste et les liens
   var items = [ ["Machin bleu", "blue"],
                   ["Machin rouge",  "red"] ];

   for (var i = 0; i < items.length; ++i) {
        var li = ul.appendChild(document.createElement("LI"));
        var a  = li.appendChild(document.createElement("A"));

          a.href = "/produits/" + items[i][1];
          a.appendChild(document.createTextNode(items[i][0]));
       }
    }
 }

La fonction addServices() serait du même acabit. Puis nous devons nous assurer que le navigateur puisse gérer ces fonctions DOM :

Sixième exemple

 function createSubMenus()
  {
   // Vérifier que les fonctions DOM à utiliser seront gérées
   // (échouer silencieusement)
     if (typeof document.getElementById != "undefined"
        && typeof document.createElement != "undefined"
        && typeof document.createTextNode != "undefined")
       {
         addProducts();
         addServices();
       }
  }

Cette fonction vérifie que les fonctions DOM principales utilisées par addProducts() et addServices() sont gérées par le navigateur. Sinon la fonction ne fait rien, elle ne nuit pas et il n'y aura pas de message d'erreur JavaScript ou d'icone de mise en garde. On appelle cette approche la détection d'objets et elle est infiniment meilleure que l'ancienne avec des scripts de reniflage des navigateurs qui cessaient de fonctionner dès que paraissait un nouveau navigateur (ou une nouvelle version d'un navigateur existant).

Enfin, pour que le navigateur appelle ces fonctions dès que la page est chargée :

Septième exemple

  if (window.addEventListener) {
     window.addEventListener("load", createSubMenus, false);
  } else if (window.attachEvent) {
     window.attachEvent("onload", createSubMenus);
  } else {
     window.onload = createSubMenus;
  }

Remarquez que ce morceau de code n'est pas contenu dans une fonction. Il ajoutera un guetteur d'événement pour l'événement "load" de la fenêtre en appellant notre fonction de création de menu immédiatement après la fin du chargement du document HTML. (Nous devons attendre jusque là afin que les attributs id soient disponibles).

Les navigateurs modernes utiliseront la fonction addEventListener() définie dans la spécification DOM niveau 2 Events, tandis que le navigateur Internet Explorer utilisera la fonction propriétaire attachEvent().

La dernière condition attrape-tout n'est pas parfaite : elle remplacera tous les gestionnaires « onload » existants créés par un script précédent. C'est à peine inaperçu. En réalité, nous aurions besoin d'une solution légèrement plus complexe pour ce cas, mais je ne veux pas compliquer inutilement les exemples.

Nous ajouterons un élément script dans la section head de notre document pour charger le fichier JavaScript externe :

<script type="text/javascript" src="/menu.js"></script>

En dernière étape, nous ajouterions le CSS de ces sous-menus et les guetteurs d'événements JavaScript pour les afficher ou les cacher, en nous assurant bien sûr de la gestion du ciblage à la fois avec la souris et avec le clavier.

La validation de formulaire

La validation de formulaire est une utilisation courante de JavaScript, mais on ne peut évidemment pas compter dessus. Si nous le faisions, quelqu'un ayant désactivé l'interprétation des scripts de son côté pourrait soumettre des données invalides et un script malfaisant détourner notre formulaire pour on ne sait quoi.

La validation des données de formulaire doit toujours avoir lieu côté serveur mais on peut vouloir lui ajouter une validation côté client pour des raisons d'efficacité. Elle profitera aux utilisateurs en leur donnant plus rapidement une action en retour et elle nous profitera en réduisant le nombre de requêtes au serveur.

En utilisant les méthodes décrites précédemment, nous pouvons ajouter une validation JavaScript inaperçue par détection d'objets. Un navigateur moderne avec JavaScript activé améliorera le processus de validation en retenant quand même la validation côté serveur pour la minorité récusant les scripts (et pour notre raison garder).

Ajax

AJAX est devenu un grand mot à la mode l'année dernière. Tout le monde doit l'utiliser, qu'il en ait réellement besoin ou non. J'ai parfois le sentiment que c'est une réponse qui court après un problème, mais c'est indéniablement une technique utile dans certaines situations courantes.

Prenons un formulaire avec deux ou plusieurs éléments select (des listes déroulantes ou des listes ouvertes) où chaque élément select dépend du précédent. Les choix imbriqués pour des types/sous-types ou pour des pays/états en constituent des exemples typiques. Selon ce que vous avez sélectionné dans la première liste, le contenu de la deuxième liste devra changer. Comment faire pour que ça fonctionne aussi bien que possible pour tous les utilisateurs ?

Nous partirons encore une fois des fondamentaux. À ce stade, ne vous préoccupez pas des scripts côté client, pensez seulement au HTML :

Huitième exemple (en HTML)

 <form action="produits.php" method="post">
  <fieldset>
   <legend>Type de produit</legend>

    <label for="type">Type</label>
     <select name="type" id="type">
      <option value="none" selected>- sélectionnez un type -</option>
      <option value="widgets">Machins</option>
      <option value="gadgets">Bidules</option>
     </select>
     <input type="submit" name="chooseType" value="Sélectionner">

     <br>
     <label for="subtype">Sous-type</label>
      <select name="subtype" id="subtype" disabled>
       <option></option>
      </select>

     <br>
     <input type="submit" name="show" value="Afficher les produits" disabled>
   </fieldset>
  </form>

Notre liste primaire (Type) est peuplée par des types de produits (Machins et Bidules). La liste secondaire (Sous-type) est vide et désactivée, et le bouton de soumission principal (Afficher les produits) est désactivé. L'utilisateur doit choisir un type de produit puis actionner l'autre bouton de soumission (Sélectionner). Le formulaire est soumis à notre script côté serveur (produits.php), qui réaffiche ensuite le formulaire avec la liste « Sous-type » peuplée des sous-types du type sélectionné (ou un message d'erreur bienveillant si aucun type n'était indiqué).

L'utilisateur peut alors sélectionner un sous-type et soumettre le formulaire avec le bouton « Afficher les produits » (qui n'est plus désactivé cette fois). S'il change d'avis et veut sélectionner un autre type, il devra à nouveau actionner le bouton « Sélectionner » pour charger les bons sous-types.

Ce n'est pas le formulaire le plus convivial au monde et il nécessite un script côté serveur rigoureux (toutefois simple), mais il fonctionne dans virtuellement tous les navigateurs. Même Lynx manie les formulaires comme celui-là.

Nous voudrions toutefois le rendre plus vif et en faciliter l'utilisation. Peupler la liste secondaire dès que la sélection a changé dans la liste primaire serait super. Cela nécessite du JavaScript. Les choix de types et sous-types sont plus souvent dynamiques que le contraire et doivent plutôt être extraits d'une base de données qu'être figés dans le code, ce qui en fait un candidat probable pour une solution AJAX.

Nous utilisons du JavaScript inaperçu pour détecter la gestion des fonctions nécessaires (principalement XMLHttpRequest). Si reconnue, nous ajoutons un gestionnaire d'événement pour la liste primaire en utilisant addEventListener() ou attachEvent() selon le navigateur de l'utilisateur. Puis nous supprimons le bouton « Sélectionner » avec la fonction DOM removeChild() car il n'a plus d'utilité et prêterait seulement à confusion.

Le guetteur d'événement ajouté ouvre une connexion asynchrone au serveur et poste une requête HTTP indiquant le type sélectionné. Le script sur le serveur interroge la base de données et retourne une réponse XML contenant les sous-types disponibles, que nous lisons alors et utilisons pour peupler la liste de sous-types (avec des fonctions DOM). Nous activons ensuite la liste de sous-types et le bouton de soumission principal.

Un navigateur avec JavaScript activé mais sans gestion AJAX pourrait soumettre le formulaire automatiquement au script sur le serveur, qui réafficherait le formulaire avec la liste secondaire peuplée, un peu comme une version sans script mais sans obliger l'utilisateur à actionner un bouton supplémentaire.

C'est un rehaussement progressif : ça fonctionne pour tout le monde mais les utilisateurs de navigateurs modernes auront une version plus conviviale. Nous les récompensons en quelque sorte d'avoir un bon navigateur sans être impolis vis-à-vis des utilisateurs de Lynx ou des employés d'entreprises dont les services informatiques sont paranoïaques. Il n'est même pas nécessaire de croire l'élément noscript peu fiable et, puisque nous utilisons une détection d'objets au lieu d'un reniflage de navigateur, il n'est pas nécessaire de mettre à jour le code JavaScript à chaque nouvelle version d'un navigateur.

Le choix d'une méthode

À l'évidence, le mode dégradé et le mode rehaussé participent tous deux à l'accessibilité d'un site Web, tout en offrant une convivialité supplémentaire à ceux qui peuvent en tirer parti. Quelle méthode choisir alors ?

Le mode rehaussé est normalement préférable au mode dégradé pour la même raison que la conception structurelle conduit généralement à une meilleure accessibilité que la conception visuelle : elle commence avec les fondamentaux simples et ajoute les ornements dessus. Pour une conception à partir de zéro, nous devrions sans hésitation penser dans le mode rehaussé.

Pour l'entretien d'un site existant, ou pour essayer d'améliorer l'accessibilité et la conformité aux standards, la situation est différente. À moins de tout récrire, notre seule option est d'offrir un mode dégradé au mieux des possibilités.

Bien sûr, on peut aussi mélanger les deux méthodes dans un site ou même dans une page. Si nous avons le choix, nos efforts devraient aller vers le mode rehaussé.

Les tests

Les tests d'accessibilité sont plus faciles à réaliser en mode rehaussé qu'en mode dégradé.

Si on travaille dans la perspective du mode rehaussé, il suffit de créer la version de base et de vérifier qu'elle fonctionne. Nous ajoutons alors les améliorations et vérifions qu'elles fonctionnent. D'accord, c'est un peu simpliste : lorsqu'on teste les améliorations, il faudra peut-être vérifier qu'elles ne cassent pas la version de base.

Si on utilise un mode dégradé (ou lorsqu'on vérifie que les améliorations ajoutées ne causent pas de problèmes dans les navigateurs moins performants) il nous faut une approche différente. Ici les fonctions avancées sont déjà présentes et peuvent être testées tout de suite. Pour vérifier qu'elles se dégradent bien gracieusement, nous devons désactiver la gestion de ces fonctions. Cela obligera parfois à tester dans un navigateur différent mais certaines choses, comme les équivalents textuels, la gestion de JavaScript ou des modules d'extension, pourront l'être en utilisant les fonctions d'accessibilité d'Opera ou la barre d'outils Web Developer dans Firefox.

En outre…

Les militants de l'accessibilité dont je suis sont parfois accusés d'être des prosélytes réactionnaires, des néo-luddites qui abhorrent tout ce qui peut rendre le Web plus agréable et distrayant.

Certains de nos détracteurs prétendent que nous interdisons d'utiliser JavaScript ou Flash dans les sites Web.

J'espère que cet article prouvera qu'ils ont tort une fois pour toute. Tout ce qui peut améliorer la convivialité ou l'esthétique est une bonne chose. Ce que je veux souligner (à l'instar de beaucoup) est le danger de compter sur des technologies non standards, brevetées ou dépendant d'une plateforme. Un agent d'utilisateur qui gère HTTP et HTML est tout ce qui devrait être nécessaire pour accéder aux informations sur le Web. Cet agent d'utilisateur devrait être capable d'accéder aux informations essentielles sur n'importe quel site professionnel.

Si l'agent d'utilisateur gère CSS, JavaScript, Flash, MathML, SVG, la vidéo incorporée et ainsi de suite, c'est super ! Ses utilisateurs profiteront d'un site de meilleur aspect et plus facile à utiliser aussi. Il peut même y avoir du contenu superflu non accessible à tel navigateur brut mais que les utilisateurs de navigateurs mieux équipés pourront apprécier.

Le mode dégradé dans une certaine mesure et le mode rehaussé spécialement permettent cette dichotomie. Il est possible d'avoir le beurre et l'argent du beurre. Ça demande parfois un peu plus de travail mais souvent ça vaut le coup.

Notes
  1. Visual vs Structural / accessites.org
© 1999-2008 yoyodesign.org — Certains droits réservés