Dégradation élégante & Amélioration progressive

Par Tommy Olsson

Dégradation élégante et amélioration progressive sont les deux faces d'une même pièce. Il s'agit, dans notre cas, de rendre un site Web accessible à tous les agents utilisateurs, tout en améliorant l'esthétique et/ou l'ergonomie pour les navigateurs plus compétents. La différence entre les deux est là où commence votre approche.

Il y a quelque temps j'ai écrit un article à propos des deux approches du design Web : Visuel contre Structurel. Les concepts de dégradation élégante et d'amélioration progressive sont étroitement liés à ces deux approches.

Dégradation élégante

La dégradation élégante est le plus vieux des deux concepts. Le terme se retrouve aussi dans d'autres domaines que la conception Web, tel que la mécanique de précision ou les systèmes électriques.

Les prémices d'une dégradation élégante sont de construire tout d'abord pour l'avant-garde et les meilleurs, puis de gérer ensuite les systèmes les moins performants. En d'autres termes, concentrez-vous sur la majorité avant de vous occuper de ceux qui ne sont pas dans la tendance. C'est tout à fait similaire à l'approche visuelle de la conception Web, où la première priorité est de faire quelque chose qui présente bien pour la plupart des visiteurs.

Vous êtes sans doute familiers avec le texte alternatif des images, où le principe de dégradation élégante est à l'oeuvre. Lorsqu'il est utilisé correctement, il fournit un texte équivalent qui exprime la même information que l'image aux utilisateurs qui ne peuvent la percevoir. Le texte équivalent n'est probablement pas aussi esthétiquement plaisant et une image peut dire plus que mille mots, donc l'expérience utilisateur est légèrement dégradée.

Utiliser une présentation à base de tableaux peut être vue comme une dégradation élégante : si les styles CSS ne peuvent être appliqués (comme dans les navigateurs très anciens) au moins la disposition de la page est maintenue. Mais cela ne fonctionne pas très bien pour les navigateurs en mode texte comme Lynx et quelques navigateurs de téléphone mobile, qui ne supportent pas les tableaux.

La balise noscript est un autre exemple de l'approche dégradation élégante. Vous fournissez une fonctionnalité basée sur JavaScript et vous ajoutez une version plus basique pour les agents utilisateurs qui ne supportent pas le JavaScript ou dont l'interprétation des scripts est désactivée côté client.

Exemple Un

<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>

La fonction JavaScript peut créer un menu où « Produits » et « Services » ont des sous-menus déroulants ou en cascade lorsque la souris de l'utilisateur survole les principales entrées. L'alternative non-JavaScript fournit un accès immédiat uniquement aux entrées principales du menu, alors que les sous-menus sont (vraisemblablement) inclus dans des éléments noscript similaires à l'intérieur des pages respectives.

Cette approche est faite pour les utilisateurs qui suivent la tendance, c'est à dire ceux qui ont un navigateur graphique qui supporte le JavaScript, mais comme elle se dégrade élégamment, ceci fonctionne aussi même pour les navigateurs en mode texte les plus modestes. Cela a aussi l'avantage de fournir un balisage HTML correct aux agents utilisateurs non-JavaScript tels que les robots des moteurs de recherche, évitant ainsi les graves problèmes de référencement posés par les menus dynamiques.

Il y a quand même un problème avec l'élément noscript. Je peux utiliser un navigateur qui supporte le JavaScript et qui l'a activé, mais il est possible que le pare-feu d'une société supprime le JavaScript entrant pour des raisons de sécurité. Dans ce cas l'élément noscript ne sera pas affiché (car mon navigateur supporte les scripts) et le code JavaScript qui devrait créer le menu n'est pas appliqué non plus, parce qu'il reste coincé derrière le pare-feu.

Dégradation pas si élégante

Dans certains cas malheureusement, on ne peut plus utiliser l'adjectif « élégant ». Le pire des cas est le code suivant :

Exemple Deux

<script type="text/javascript" src="/menu.js"></script>
<noscript>
  <p>Utilisez un navigateur qui supporte le JavaScript SVP.</p>
</noscript>

Tolérable sur un site amateur seulement destiné à la famille et aux amis, ce type de message est totalement inacceptable sur un site web sérieux.

En tant que concepteurs Web ou développeurs, nous n'avons pas le droit de dire à nos visiteurs quel navigateur ils « devraient » utiliser ; ni le droit de dire à quiconque « d'activer le JavaScript ». Nous ne savons pas pourquoi ce visiteur utilise Lynx ou pourquoi ce visiteur a « désactivé le JavaScript » côté client. Ils ne peuvent peut-être même pas avoir l'option « changer de version » ou « activer le JavaScript » à cause des contraintes de bande passante, de matériel ou de budget ; ou à cause de la politique du département informatique ; ou parce qu'ils n'utilisent pas leur propre ordinateur.

Un site qui se dégrade élégamment vaut bien mieux qu'un site totalement inutilisable pour une partie de la population, mais ce n'est pas la meilleure approche. Comme pour l'approche visuelle de la conception, il est souvent difficile de démarrer avec toutes les fonctionnalités puis de les retirer une à une, sans que tout s'effondre.

Amélioration progressive

L'amélioration progressive est connue (au moins sous ce nom) depuis 2003, lorsque Steve Champeon a commencé à l'employer sur Webmonkey et pendant la conférence de SXSW. L'amélioration progressive repose sur un principe radicalement différent de la dégradation élégante : commencer par la version de base, puis ajouter des améliorations pour ceux qui peuvent les gérer. Encore une fois, comparons cela aux approches visuelles : c'est la même idée de base que dans la conception structurelle. On commence par le balisage et on ajoute des styles par dessus, ce qui est une amélioration progressive.

L'exemple le plus fréquent de l'amélioration progressive est probablement la feuille de style CSS externe. Elle est ignorée par les navigateurs non CSS (qui affichent donc uniquement le balisage simple et son rendu en fonction de leur feuille de style interne) mais est appliquée par les navigateurs graphique modernes, améliorant ainsi l'esthétique et l'ergonomie pour les navigateurs les plus courants et les plus capables.

D'autres exemples d'améliorations progressives sont les diverses techniques de remplacement d'image, la méthode Flash Satay et (quelquefois) AJAX.

Les améliorations progressives à l'aide de JavaScript deviennent plus fréquentes ces temps-ci. L'explication de ce phénomène est connue sous le nom de JavaScript non-intrusif. Un script non-intrusif est ignoré par les agents utilisateurs qui ne le supportent pas, mais est appliqué par les systèmes plus performants. Exactement comme une feuille de style externe.

Examinons à nouveau le menu vu précédemment comme exemple d'une dégradation élégante. Comment cela aurait-il fonctionné en utilisant une amélioration progressive ?

Nous commencerons en créant notre balisage, visant le plus petit dénominateur commun : HTML. Un menu 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.

Exemple Trois

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

Cela fonctionnera partout de Lynx et Mosaic 1.0 aux dernières versions d'Opéra, Firefox et Safari. Les robots d'indexation de Google et ses cousins arachnoïdes adoreront ça eux aussi.

À la prochaine étape nous allons apporter des améliorations pour une vaste majorité des utilisateurs dont les navigateurs supportent les CSS. Nous allons ajouter des règles dans une feuille de style externe. Après l'ajout d'un élément link faisant référence à cette feuille de style externe, cela se présente bien mieux pour la plupart des visiteurs, mais ce n'est en aucun cas au détriment des utilisateurs de Lynx ou des robots d'indexation de Google. (Ok, ils auront à télécharger quelques octets en plus, mais cela sera négligeable même sur une petite connexion modem ou sur un téléphone portable GSM.)

Mais on peut encore améliorer cela en ajoutant des sous-menus déroulants ou en cascade aux items principaux, en utilisant du JavaScript non-intrusif. Pour réduire la quantité de code, on commence par assigner des identifiants à la liste des items :

Exemple Quatre

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

Puis nous créons un fichier JavaScript séparé contenant les fonctions suivantes :

Exemple Cinq

function addProducts()
{
  // Trouve l'élement li auquel nous ajouterons le sous-menu
  var parent = document.getElementById("produits");

  // On s'assure qu'il existe (sinon on sort sans bruit)
  if (parent)
  {
    // Créé une liste imbriquée non-ordonnée
    var ul = parent.appendChild(document.createElement("UL"));

    // Ajoute les items et les liens de la liste
    var items = [ ["Gadgets bleus", "bleu"],
                   ["Gadgets rouges",  "rouge"] ];

    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() sera très similaire. Nous devons nous assurer ensuite que le navigateur puisse gérer ces fonctions DOM :

Exemple Six

function createSubMenus()
{
  // S'assure que les fonctions DOM que l'on va utiliser sont supportées
  // (sinon sort sans faire de bruit)
  if (typeof document.getElementById != "undefined"
        && typeof document.createElement != "undefined"
        && typeof document.createTextNode != "undefined")
  {
    addProducts();
    addServices();
  }
}

Cette fonction s'assure que les principales fonctions DOM utilisées par addProducts() et addServices() sont supportées par le navigateur. Si ce n'est pas le cas, la fonction ne fait rien ; cela ne cause aucun mal et il n'y aura aucun message d'erreur JavaScript ou d'icône d'avertissement. Cette approche, appelée détection d'objet, est infiniment meilleure que celles fondées sur des scripts de détection du navigateur, qui s'arrêtaient de fonctionner dès que sortait une mise à jour ou un nouveau navigateur.

Et pour finir, il faut que le navigateur appelle ces fonctions dès que la page a été chargée.

Exemple Sept

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

Notez que ce morceau de code n'est pas inclus dans une fonction. Cela ajoutera un gestionnaire d'évènement sur l'évènement « load » de la fenêtre, appelant nos fonctions de création de menu immédiatement après que le document HTML a été chargé. Nous devons attendre que le HTML soit complètement chargé, sinon les identifiants ne seront pas disponibles pour notre script.

Les navigateurs modernes utiliseront la fonction addEventListener(), présente dans la norme DOM niveau 2 (évènements), alors que Internet Explorer utilisera sa fonction propriétaire attachEvent().

La dernière clause else n'est pas parfaite : elle remplacera s'il y en a tous les gestionnaires d'évènements déjà définis. C'est presque non-intrusif. En réalité nous aurions besoin d'une solution légèrement plus compliquée pour ce cas, mais je ne souhaite pas faire des exemples inutilement compliqués.

Nous allons maintenant ajouter un élément script dans la section HEAD de notre document afin de charger le fichier JavaScript externe :

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

Comme étape finale nous allons ajouter pour ces sous-menus, ainsi que pour les gestionnaires JavaScript, des règles CSS pour les afficher ou les cacher, en permettant bien entendu l'utilisation de la souris et du clavier.

Validation de formulaire

Le JavaScript est couramment utilisé pour la validation de formulaire, mais on ne peut évidemment pas compter que sur lui. Si nous faisions ça, un visiteur qui aurait désactivé JavaScript ou un script malfaisant pourraient utiliser notre formulaire pour faire Dieu-sait-quoi.

La validation des données d'un formulaire doit toujours être faite côté serveur, mais pour des raisons d'efficacité on peut souhaiter utiliser en plus la validation côté client. Cela bénéficiera aux utilisateurs en leur donnant un retour d'information rapide. Cela nous arrangera aussi en réduisant le nombre de requêtes vers nos serveurs.

En utilisant les méthodes exposées ci-dessus, nous pouvons ajouter notre validation JavaScript de manière non-intrusive avec la détection d'objet. Un navigateur moderne avec le JavaScript activé, améliorera le processus de validation, alors que nous conservons toujours un système de validation pour ceux qui ont un navigateur plus ancien (et en plus on préserve notre santé mentale).

AJAX

AJAX est devenu un terme à la mode l'année dernière. Tout le monde doit l'utiliser, qu'on ait vraiment besoin de lui ou pas. J'ai parfois l'impression qu'on cherche encore le problème auquel il répond. Mais on ne peut pas nier que c'est une technique pratique dans certaines situations.

Prenez un formulaire avec au moins deux éléments select (liste déroulante ou à choix multiples) où chaque select est dépendant du précédent. Les exemples typiques permettent d'affiner la recherche par catégorie/sous-catégorie, pays/département, etc. Selon ce que vous avez choisi dans la première liste, le contenu de la seconde liste devrait changer. Comment réaliser cela de la meilleure façon qui soit pour tous les utilisateurs ?

Nous allons une fois encore commencer avec les bases. Ne pensez pas au script côté client à cette étape ; pensez uniquement au support HTML.

Exemple Huit (en HTML)

<form action="produits.php" method="post">
  <fieldset>
    <legend>Catégorie de produit</legend>
    <label for="categorie">Catégorie</label>
    <select name="categorie" id="categorie">
      <option value="none" selected>- Sélectionnez une catégorie -</option>
      <option value="gadgets">Gadgets</option>
      <option value="bidules">Bidules</option>
    </select>
    <input type="submit" name="selectionner" value="Sélectionner" />
    <br />
    <label for="souscategorie">Sous-catégorie</label>
    <select name="souscategorie" id="souscategorie" disabled>
      <option></option>
    </select>
    <br />
    <input type="submit" name="afficher" value="Afficher les produits" disabled />
  </fieldset>
</form>

Notre liste primaire (categorie) est remplie avec nos catégories de produits : gadgets et bidules. Notre liste secondaire (souscategorie) est vide et désactivée, et le bouton submit principal (Montrer les produits) est désactivé. Un utilisateur choisit une catégorie de produit et active alors l'autre bouton submit (« Sélectionner »). Le formulaire est soumis à notre script côté serveur (produits.php), qui réaffichera alors le formulaire avec la liste des sous-catégories remplie avec les sous-catégories de la catégorie sélectionnée (ou affichera un gentil message d'erreur si aucune catégorie n'est spécifiée).

L'utilisateur peut alors sélectionner une sous-catégorie et soumettre le formulaire en utilisant le bouton « Afficher les produits » (qui, cette fois, n'est plus désactivé). S'il change d'avis et veut sélectionner une autre catégorie, il devra activer à nouveau le bouton « Sélectionner » afin de charger les bonnes sous-catégories.

Ceci n'est pas le formulaire le plus convivial au monde et il a plutôt besoin de quelques scripts fastidieux côté serveur, mais il fonctionne virtuellement sur tous les navigateurs. Même Lynx gère des formulaires comme celui-ci.

Mais nous voudrions le rendre plus rapide et plus facile à utiliser. Ce serait sympa de remplir la liste secondaire dès que la sélection change dans la liste primaire. Cela nécessite JavaScript. Le plus souvent le choix des catégories et des sous-catégories est dynamique et a besoin d'être récupéré d'une base de données plutôt que d'être codé en dur. Ce formulaire est donc un candidat potentiel à une solution AJAX.

Nous allons utiliser du JavaScript non-intrusif pour détecter le support des caractéristiques nécessaires (principalement XMLHttpRequest). Si supporté, nous ajouterons un gestionnaire d'évènement pour la liste primaire en utilisant addEventListener() ou attachEvent(), selon le navigateur de l'utilisateur. Puis nous enlèverons le bouton « Sélectionner » en utilisant la fonction removeChild() du DOM, parce qu'il ne sera plus nécessaire mais seulement déroutant.

Le gestionnaire d'événement ajouté ouvrira une connexion asynchrone vers notre serveur et enverra une requête HTTP indiquant le type sélectionné. Le script côté serveur interrogera la base de données et retournera une réponse XML contenant les sous-catégories disponibles, qu'on analysera et qu'on utilisera pour remplir la liste des sous-catégories (avec les fonctions DOM). Puis nous pourrons activer la liste des sous-catégories et le bouton submit principal.

Un navigateur avec JavaScript activé et qui ne supporte pas AJAX pourra soumettre le formulaire automatiquement à un script côté serveur qui réaffichera le formulaire avec la liste secondaire remplie, tout comme la version sans script mais sans exiger que l'utilisateur active un bouton supplémentaire.

C'est une amélioration progressive : ça marche pour tout le monde, mais les utilisateurs de navigateurs modernes verront une version plus accessible. En quelque sorte, nous les récompensons d'utiliser un bon navigateur, sans être impoli avec les utilisateurs de Lynx ou les employés de sociétés qui ont un département informatique paranoïaque. Nous n'avons pas à faire confiance à l'élément noscript qui est peu fiable, et puisqu'on utilise la détection d'objet plutôt que la détection du navigateur, nous n'avons pas à maintenir à jour le JavaScript pour chaque nouvelle version de navigateur.

Choisir une méthode

La dégradation élégante et l'amélioration progressive améliorent toutes deux l'accessibilité d'un site, et en augmentent l'ergonomie pour ceux qui sont correctement équipés. Alors laquelle de ces deux méthodes choisir ?

Les améliorations progressives sont généralement préférables aux dégradations élégantes, pour la même raison que la conception structurelle mène généralement à une meilleure accessibilité qu'une conception visuelle : on commence avec les mêmes bases simples puis on ajoute des embellissements. Lorsque nous partons de zéro, l'approche progressive est définitivement recommandée.

Si nous maintenons un site existant, en essayant d'améliorer l'accessibilité et la conformité aux standards, la situation est différente. À moins de vouloir tout réécrire, notre seul choix est de fournir des dégradations élégantes du mieux que l'on peut.

Bien sûr, il est également possible de mélanger les deux méthodes sur un site, ou même sur la même page. Les améliorations progressives sont ce que l'on doit rechercher, même si on a le choix.

Tester

Tester l'accessibilité est beaucoup plus facile avec des améliorations progressives qu'avec des dégradations élégantes.

Pour l'amélioration progressive, il suffit de tester que la version de base fonctionne, puis ajouter et tester nos améliorations. D'accord, je simplifie un peu : on peut avoir besoin de vérifier que les améliorations n'abîment pas la version de base.

Si nous utilisons des dégradations élégantes (ou lorsque l'on vérifie que les améliorations progressives ne causent pas de problèmes aux agents utilisateurs les moins performants), nous avons besoin d'une approche différente. Maintenant, les fonctionnalités avancées sont déjà présentes et peuvent être testées sans difficulté. Afin de vérifier qu'elles dégradent réellement de manière élégante, on doit désactiver le support de ces fonctionnalités. Quelquefois cela exigera des tests dans différents navigateurs, mais certaines choses (comme les textes alternatifs, le support de JavaScript ou des plugins) peuvent être contrôlées en utilisant les fonctionnalités d'accessibilité d'Opéra ou avec la barre d'outils Web Developer dans Firefox.

Par ailleurs...

Les évangélistes de l'accessibilité comme moi, sont parfois accusés par certains d'être des réactionnaires fanatiques, de nouveaux Luddistes qui détestent tout ce qui rend le Web plus agréable et divertissant. On nous reproche souvent d'interdire l'utilisation de Flash et de JavaScript.

J'espère que cet article leur prouvera une fois pour toutes qu'ils ont tort. Quelque chose qui améliore l'accessibilité ou l'esthétique est une bonne chose. Je souhaite montrer (et je ne suis pas le seul) qu'il est dangereux de compter sur des technologies non-standard, propriétaires ou dépendantes d'une plate-forme. Tout ce qui devrait être demandé pour accéder à l'information sur le Web est un agent utilisateur qui supporte HTTP et le HTML. Un tel agent utilisateur devrait être capable d'accéder aux informations vitales sur n'importe quel site professionnel.

Si l'agent utilisateur supporte les CSS, le JavaScript, le Flash, MathML, SVG, les vidéos embarquées et ainsi de suite, c'est super ! Ces utilisateurs en bénéficieront en voyant un site plus facile à utiliser et plus agréable à regarder. Il peut même y avoir du contenu non critique qui ne sera pas accessible aux navigateurs sans option, mais que les utilisateurs avancés pourront apprécier.

L'amélioration progressive, et dans une moindre mesure la dégradation élégante permettent de satisfaire deux objectifs simultanément. Pour une fois, on peut avoir le beurre et l'argent du beurre. Cela exige parfois un petit peu plus de travail, mais ça en vaut souvent la peine.

Fiche technique

À propos de l'auteur

Tommy Olsson travaille en Suède à Sundsvall comme webmestre au Swedish Companies Registration Office et donne gratuitement de son temps libre comme serviteur atitré d’Ida et d’Emil, ses deux chats préférés, en leur préparant à manger, en leur ouvrant les portes ou encore en leur servant de couverture chauffante. Surnomé « TOOLman », Tommy est aussi celui sans qui The Autistic Cuckoo, malheureusement désormais fermé, n’aurait jamais existé.

Article du même auteur

Articles similaires

Voici la liste des dix articles les plus récents en rapport avec cet article :

Tous niveaux

Accessibilité

© 2001-2016 Pompage Magazine et les auteurs originaux - Hébergé chez Nursit.com ! - RSS / ATOM - About this site