Intelligent & Responsive UI - Une interface pensée pour l'utilisateur

old_chimi.jpg Il y a peu de temps, on m’a demandé au boulot de réaliser une interface graphique entièrement nouvelle pour un outil de suivi interne. Le délai était très court – il s’agissait d’un projet interne non-rémunéré – mais l’interface devait néanmoins s’adapter à l’affichage sur iPhone.

Parti du constat qu’un site Web beau et simple est plus attrayant qu’une interface moche et basique, et faisant partie des futurs utilisateurs, j’ai voulu faire en sorte que le design et les interactions soient le plus possible optimisés pour une utilisation agréable et rapide. A force de glaner des idées à droite à gauche, notamment sur les réseaux sociaux ou chez Google, je me suis rendu compte qu’une véritable interface graphique optimisée RIA (Rich Internet Application) pouvait intégralement changer son utilisation.

Voici donc une collection de « bonnes pratiques » pour réaliser des interfaces graphiques intelligentes et intuitives, agréables à utiliser et surtout … humaines.

Pensez « light »

La première chose à penser quand on commence à réaliser le design d’un site Internet c’est la simplicité. En effet, plus une interface graphique est simple, épurée et agréable à regarder, plus elle sera utilisée. Dans cette optique, adoptez un design léger, avec des couleurs pas trop contrastées ni trop saturées. Ensuite, pensez à intégrer discrètement les fonctionnalités. Par exemple, au lieu d’afficher plusieurs icônes à côté d’une ligne d’un tableau pour les fonctionnalités comme l’édition ou la suppression, affichez une unique icône qui, lorsqu’elle sera cliquée, affichera plus d’information. Essayez d’épurer au maximum votre interface.

Une bonne « base » en CSS

Avant de commencer à travailler sur une nouvelle page, assurez-vous de bien remettre à zero tous les paramètres afin de ne pas être gêné plus tard.

En premier lieu, activez la possibilité de spécifier des hauteurs de blocs en pourcentages grâce à cette ligne de code :

html { height: 100%; font-size: 100%; -webkit-text-size-adjust: 100%; }

Au passage, vous constatez que les paramètres de tailles de polices sont eux-aussi ajustés. Ensuite, cette grosse portion de code permet de réinitialiser l’affichage des balises :

html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}

L’étape suivante consiste à s’occuper les liens. Il y a deux choses à ne pas oublier qui sont très importantes :

  1. La couleur d’un lien visité doit être bien différente de celle des liens non-visités. Cette propriété est très importante car elle va grandement aider la navigation sur vos pages.
  2. Indiquez clairement que le lien a été cliqué. Sur les périphériques mobiles tactiles, il arrive que le « clic » ne fonctionne pas convenablement, incitant les utilisateurs à répéter l’opération si rien ne semble avoir bougé. En colorant les liens lors du clic, vous montrez que l’action a été prise en compte.

Voici un peu de code CSS pour faire tout ça :

a { cursor: pointer; color: blue; }
a:visited { color: purple; }
a:active { color: red; }
a:focus { color: red; }

Vous remarquerez aussi que l’on force l’affichage du curseur « pointer » pour tous les liens. Par défaut, les navigateurs n’affichent ce curseur que si le lien est doté d’un attribut « href ». Or, de nos jours, avec la programmation côté client en Javascript, il peut arriver que le comportement d’un clic sur un lien soit uniquement géré en Javascript, rendant inutile l’utilisation de cet attribut.

Ensuite, un petit bout de code CSS qui fait des merveilles :

img, object, embed, video { max-width: 100%; }

Il limite automatiquement la taille des éléments à la largeur maximum du conteneur. Ça permet, entre-autre, d’importer les images directement dans votre page sans passer par des versions miniaturisées : avec ce morceau de code, vous êtes certain que vos images ne dépasserons pas les dimensions de leurs conteneurs.

Un layout fluide et répondant

Aujourd’hui, les périphériques qui peuvent afficher des pages Web sont nombreux : PC, portables, ultra-portables, téléphones, tablettes… Il est donc très important de proposer une interface graphique capable de s’adapter à n’importe quelle résolution d’écran, et de gérer le changement d’orientation du périphérique.

Pour un affichage sur écran traditionnel, il y a deux écoles :

  1. Ceux qui utilisent une taille fixe. De nos jours, on considère que la majorité des internautes possèdent un écran dont la résolution est au moins 1024 x 768 pixels. Le plus souvent on choisira une taille légèrement inférieur, 1000 pixels de largeur par exemple. Le tout étant de prendre une valeur paire qui sera plus simple à diviser en deux.
  2. Ceux qui se mettent au « flow layout ». Dans ce cas, les tailles des éléments sont fixées en pourcentages, et s’adaptent en fonction de la résolution.

Les deux idées se défendent, et la première est souvent la plus simple. Mais quand on veut faire les choses bien, il faut faire un design adaptatif. Mais quand on commence avec les pourcentages, il ne faut pas s’arrêter aux blocs principaux qui composent la structure générale du site. Toutes les marges doivent être en pourcentages, ainsi que les hauteurs de lignes. Vous pouvez très bien cumuler avec des valeurs statiques en pixel pour certains éléments, mais vous devez conserver globalement les pourcentages comme unité.

Ensuite, comment faire un design « répondant » (ou « adaptatif ») ?

Le premier paramètre qui peut être utilisé c’est l’événement onorientationchange qui s’utilise sur la balise body. Un petit code très sympa que j’ai trouvé sur le site de Jay Salvat permet de récupérer automatiquement cet événement, et d’attribuer une classe à la balise body en fonction :

onorientationchange

body[orient="portrait"] {
background:#FF0000;
}
body[orient="landscape"] {
background:#000;
}

Code CSS

function updateOrientation() {
switch (window.orientation) {
case 0 :   orient = 'portrait'; break;
case -90 : orient = 'landscape'; break;
case 90 :  orient = 'landscape'; break;
case 180 : orient = 'portrait'; break;
}
document.body.setAttribute('orient', orient);
}

Code Javascript

<body onorientationchange="updateOrientation();">

Code HTML

@media

Ensuite, vous pouvez utiliser la « fonction » CSS @media pour exécuter du code uniquement dans certains cas :

@media only screen and (max-device-width: 480px) {
#body { background : red ;}
}

Code CSS spécifique aux iPhones

@media only screen and (max-device-width: 480px) and (orientation: landscape) {
#body { background : blue ;}
}

Code CSS spécifique aux iPhones en mode paysage

@media only screen and (device-width: 800px) {
#body { background : blue ;}
}

Code CSS spécifique pour les petits écrans.

La taille du texte

Un autre paramètre qui doit varier en fonction la résolution : la taille des textes. En effet, le CSS est très limité de ce côté-là : il ne permet pas d’utiliser des variables pour calculer des dimensions. Il faut donc tricher, et utiliser Javascript à la rescousse.

L’astuce est très simple : on va modifier dynamiquement la taille du texte au niveau de la balise body. Comme toutes les autres dimensions sont exprimées en pourcentages, tous les textes se verrons affectés.

La démonstration se trouve ici.

J’ai fais une petite fonction en utilisant jQuery qui permet de faire ça très simplement :

function autoFontSize(width, fontSize) {
var body = $('body').css('font-size', fontSize + 'px');
$(window).resize(function () {
var size = $(this).width() / width * fontSize;
if (size < fontSize) {
size = fontSize;
}
body.css('font-size', parseInt(size) + 'px');
}).trigger('resize');
}

Fonction qui redimensionne la taille de la police du body.

Ensuite, deux choses. Premièrement, mettre le code CSS suivant :

html, body {
font-size: 100%;
height: 100%;
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
}
* { font-size: 100%; }

Code CSS

Tous les éléments de votre page vont se retrouver à la même taille par défaut. Vous devez donc configurer manuellement la taille de tous les éléments en plus.

Deuxièmement, lancer la fonction quand la page est prête :

<script>
$(function () {
autoFontSize(1024, 14);
});
</script>

Code HTML

J’ai fais un petit exemple qui se trouve ici.

Pensez aux mobiles

Pour continuer dans la lignée des trucs à bien respecter aujourd’hui pour faire un site Web affiché convenablement sur les mobiles, c’est le viewport.

Le viewport correspond à la partie visible de la page Web. Quand on zoom, on diminue le viewport. Une bonne pratique consiste à demander au navigateur d’afficher un viewport de la même taille que l’écran, affichant ainsi le site au ratio 1:1.

<meta name="viewport" content="width=device-width; initial-scale=1.0">

Pour désactiver le zoom, utilisez le code suivant :

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

Sur les mobiles, les événements javascript ne se comportent pas tous comme prévu. Cela est causé principalement par la navigation tactile.

  • Mouseover et Mousemove ne réagissent pas car le mouvement du doigt sur l’écran fait défiler la page.
  • Keypress, Keyup et Keydown ne sont pas pris en compte hors des textareas.
  • Click, Mousedown et Mouseup sont étrangement appelés en même temps quand le doigt quitte l’écran.
  • Doubleclick ne se déclenge pas, le Double-Tap effectue un zoom quoi qu’il arrive et un event.preventDefault() n’y changera rien.
  • Le One-finger panning déclenche un onScroll une fois le mouvement stoppé.
  • Le Two-finger panning déclenche un mouseWheel si l’élément est scrollable.

Enfin, concernant les événements toujours, veillez à ne pas intégrer dans votre interface des éléments qui ne sont visibles QUE lors du mouseover. Cet événement n’étant pas supporté par les mobiles (pas encore disons..) ces fonctionnalités n’apparaitrons pas à ces visiteurs.

Optimiser l'ergonomie

Pendant toute la réalisation, vous devez penser :

  • A l’aspect graphique des éléments : ils doivent être clairement identifiables, ainsi que leur fonction. Par exemple, un bouton pour supprimer un fichier doit avoir un design de bouton (un fond coloré et une bordure par exemple) indiquant que l’élément est cliquable. Ainsi qu’une icône indiquant clairement l’action (un fichier avec une petite croix rouge évoquant la suppression par exemple) ;
  • A l’emplacement des éléments : positionnez vos éléments de manière logique. Le plus souvent le logo se trouve en haut, ainsi que le menu. Les « options » sont souvent déportées vers la droite. Pensez aussi au sens de lecture : dans les langues latines, la lecture va du coin supérieur gauche au coin inférieur droit. Ainsi, si votre page inclus une logique de navigation (par exemple, pour un site de réservation d’hôtel, la première étape est filtrer les hôtels par critères, en suite d’en sélectionner un), le bouton permettant d’aller à l’étape suivante (ici, la sélection d’un hôtel) devra se trouver naturellement en bas à droite de la description de l’hôtel.

Pour vous aider, reculez vous de votre écran, et demandez vous :

où irais-je naturellement chercher cette fonctionnalité ?

Globalement, veillez à ne pas surcharger l’IHM. N’affichez les « options » que si l’utilisateur le demande.

Optimiser la navigation

Pour que vos visiteurs puissent naviguer convenablement sur votre site, il est très important qu’ils puissent utiliser le bouton de navigation « Retour ». C’est d’ailleurs le gros problème de la majorité des sites en flash : quand l’utilisateur souhaite revenir en arrière, il se retrouve sur la page précédente, le plus souvent Google. Et le plus souvent, il ne revient pas.

Avec Javascript, il est très simple de combiner un site en Ajax avec cette fonctionnalité : il suffit d’utiliser l’event hashchange. Le « hash » d’une URL correspond au dernier fragment, celui après le site dièse, qui permet de renvoyer à une ancre normalement. Le fait de cliquer sur un lien pointant vers une ancre s’enregistre dans l’historique du navigateur, c’est donc cette astuce qui va nous permettre de gérer l’ajax ET la navigation.

Personnellement, je pense qu’il faut toujours prendre en compte le fait que les Javascripts sont désactivés sur certains navigateurs. Et notamment, les bots des moteurs de recherche ! Donc il faut faire en sorte de cumuler une navigation « classique » avec une navigation « améliorée » à la sauce Web 2.0. Pour expliquer, j’ai fais un petit exemple.

Basiquement, le site est découpé en trois pages : home, summary et contents. En navigation « traditionnelle », chaque page est autonome, et peut s’afficher convenablement. Dans les fichiers home, summary et contents, vous constaterez qu’un test est fait : savoir si la variable $_GET['fragment'] est définie. En fonction de cette variable, la page renverra soit un fragment de HTML (uniquement le contenu) soit toute la page (le contenu + les balises head et body). Ça, c’est justement pour le mode asynchrone.

Dans la page index.html, vous trouverez le petit morceau de code qui fait tout le travail. Ici encore, j’utilise la librairie jQuery pour manipuler les éléments de la page plus simplement.

$(function () {
// On transforme les liens du menu ajax en ancres
$('#ajaxmenu a').each(function () {
$(this).attr('href', '#!' + $(this).attr('href'));
});
// Quand le hash change, on demande la page en ajax
$(window).bind('hashchange', function (e) {
if (location.hash == '') {
return false;
}
var page = location.hash.substr(2, location.hash.length - 6);
if (page == 'home' || page == 'summary' || page == 'contents') {
$('#contents')
.html('

Loading...

') .load(page + '.php?fragment=true'); } e.preventDefault(); return false; }).trigger('hashchange'); });

Ce code fait deux choses :

  1. Transformer tous les liens du menu ajax en ancres. C'est-à-dire, rajouter le caractère dièse devant l’URL.
  2. Suivre les changements de l’URL et plus particulièrement du hash. Dans ce cas, si le hash corresponds à une page valide, on change le contenu directement en ajax.

Les bénéfices de cette méthode sont évidents : d’une part, on propose une navigation traditionnelle aux moteurs de recherche qui vont pouvoir indexer le contenu sans soucis ; et d’autre part on offre au visiteur une navigation améliorée.

Bon, cet exemple est très sommaire. Sur un vrai cas, les fichiers home, summary et contents ne seraient pas de simples duplications, mais des fichiers générés. D’autre part, on ne traite pas ici les erreurs concernant la requête ajax. C’est un exemple quoi…

Par contre, ne négligez pas l’aspect « agrément » de l’ajax : le fait ne pas avoir à recharger entièrement une page est très important pour le ressenti utilisateur. Dans nos sociétés modernes où l’information coule à toute vitesse, une interface utilisateur réactive et dynamique est très appréciée, voir obligatoire.

Les permaliens

Aussi, pensez aussi aux permaliens : des liens permanents vers une ressource en particulier. Pour votre bon référencement, veuillez à ce qu’il n’y ait qu’une syntaxe de lien vers une page. Concrètement, évitez de multiplier les « orthographes » des liens. Par exemple : si la page « toto » peut être obtenue avec les urls « /index.php?page=toto » et « /pages/toto.html », gardez-en une seule et utilisez la partout.

Optimisez l’organisation de votre contenu

Pensez bien à organiser proprement mais simplement votre contenu. Limitez en cela le niveau de profondeur de votre arborescence. Aidez vous avec des onglets, ou des liens « En savoir plus » qui dévoient davantage de contenu. Faites en sorte que la navigation dans les profondeurs de votre site ne se fasse qu’en 3 ou 4 clics maximum.

N’oubliez pas aussi que votre page doit donner envi de farfouiller, envi de jouer avec les options. L’événement onmouseover est très bon pour ça : il permet d’afficher d’autres contenus en fonction d’où se balade le visiteur sur votre page.

Essayez de passer votre curseur au dessus du menu de gauche.

Orientis vero limes in longum protentus et rectum ab Euphratis fluminis ripis ad usque supercilia porrigitur Nili, laeva Saracenis conterminans gentibus, dextra pelagi fragoribus patens.

Has autem provincias, quas Orontes ambiens amnis imosque pedes Cassii montis illius celsi praetermeans funditur in Parthenium mare.

Qui cum venisset ob haec festinatis itineribus.

Incenderat autem audaces usque ad insaniam homines ad haec, quae nefariis egere conatibus, Luscus quidam curator urbis subito visus: eosque ut heiulans baiolorum praecentor ad.

Code HTML

Quicksearch

Le quicksearch est – à mon avis – la fonctionnalité la plus importante d’une interface graphique optimisée pour l’utilisation intensive.

Dans son concept, le quicksearch permet de faire une recherche DANS la page avant de lancer une vraie recherche sur une autre page spécialisée. Voici une petite démonstration :

Quicksearch :  X
Filter by:
Ma liste des films
Name Description Seen
Machine Gun Preacher The story of Sam Childers, a former drug-dealing biker tough guy who found God and became a crusader for hundreds of Sudanese children who've been forced to become soldiers. no
Sherlock Holmes Detective Sherlock Holmes and his stalwart partner Watson engage in a battle of wits and brawn with a nemesis whose plot is a threat to all of England. yes
Snatch Unscrupulous boxing promoters, violent bookmakers, a Russian gangster, incompetent amateur robbers, and supposedly Jewish jewelers fight to track down a priceless stolen diamond. yes
Fight Club An office employee and a soap salesman build a global organization to help vent male aggression. yes
12 Angry Men A dissenting juror in a murder trial slowly manages to convince the others that the case is not as obviously clear as it seemed in court. no
The Shawshank Redemption Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency. yes

Quicksearch peut servir à faire des tri ou des recherches.

Il s’agit d’une petite liste de films. Le champ quicksearch se trouve en haut à droite. Lorsque vous commencez à taper, la recherche s’effectue en même temps. Directement, vous les films qui ne contiennent pas les termes recherchés disparaissent, laissant le champ à ceux qui correspondent.

Regardons un peu ce qui a été mis dans le marquage HTML :

<table>
<tbody>
<tr quicksearch="movie/status:notseen/Machine Gun Preacher/The story of ...">
<td>Machine Gun Preacher</td>
<td>The story of Sam Childers, a former drug-dealing biker
tough guy who found God and became a crusader for hundreds
of Sudanese children who've been forced to become soldiers.</td>
<td><img src="public/divers/red.png" title="Not seen" alt="no" /></td>
</tr>
<tr quicksearch="movie/status:seen/Sherlock Holmes/Detective Sherlock ...">
<td>Sherlock Holmes</td>
<td>Detective Sherlock Holmes and his stalwart partner Watson
engage in a battle of wits and brawn with a nemesis whose plot
is a threat to all of England.</td>
<td><img src="public/divers/accept.png" title="Seen" alt="yes" /></td>
</tr>
(...)
</tbody>
</table>

Ajoutez simplement les éléments à rechercher dans un attribut.

En fait, tout se passe autour de l’attribut quicksearch. On va y enregistrer tout ce qui est « important » pour la recherche. De manière tout à fait arbitraire, j’ai choisi que la slash (/) servirait à délimiter les variables, et que les deux-points (:) serviraient à donner assigner une valeur à une variable. Ici, j’ai inclus un type (movie), un status (notseen ou seen), le titre du film ainsi que sa description. C’est donc ici que quicksearch va chercher.

Le système est très souple : il peut permettre de sélectionner un item en particulier par son ID ; ou bien un groupe d’items par rapport à une caractéristique commune ; etc…

En haut à gauche, vous trouvez un système de filtre. Sélectionnez un status (seen ou notseen) et regardez ce qui se passe dans le champ quicksearch : le select se sert tout simplement du quicksearch pour filter les items ayant le status demandé. Sympa non ?

Comme quicksearch fait disparaitre les éléments ayant un attribut quicksearch qui ne corresponds pas à la recherche, vous devez vous assurer que l’élément ayant l’attribut est bien le conteneur graphique de l’entité. Je m’explique : dans cet exemple, l’attribut quicksearch est ajouté sur une balise TR, car si elle disparait, le film qu’elle contient (l’entitée) est bien masqué. Ça aurait beaucoup moins bien marché sur une balise TD par exemple.

Enfin, le bouton reset permet de réinitialiser la vue. Je n’utilise pas le champ de formulaire search (HTML5) car les navigateurs n’envoient pas encore d’événement quand le bouton reset est activé.

Normalement, le champ quicksearch est automatiquement mis en focus quand la page se charge. Ici, c’est le champ de recherche « traditionnel » de mon site qui prend le focus. Mais le fait est qu’à l’usage, avoir son curseur directement dans le champ de quicksearch permet de trouver très rapidement ce que l’on cherche.

Pour le code Javascript de quicksearch, regardez dans les sources ^^

Pour déclencher le quicksearch en dehors de l’utilisation normale par le champ de recherche, vous avez le choix :

  1. Avec la fonction quickSearch :
    quickSearch('comics');
  2. Par un lien au sein de la même page
    <a href="#qs-comics">Comics</a>
  3. Par un lien vers une autre page
    <a href="index.html?qs=comis">Comics</a>

Quickaction : amélioration du Quicksearch directement en javascript :

Le quickaction peut être défini ainsi :

Si avec le quicksearch vous arrivez à ne filter qu’un unique élément, appuyez sur entrée pour continuer.

Concrètement, supposons que vous soyez en train de rechercher un film. Après avoir utilisé quicksearch, vous avez trouvé votre film. Il n’y a que lui d’affiché. Au lieu de reprendre votre souris pour cliquer dessus, appuyez sur entrée, et vous arrivez sur la fiche de description !

Maintenant que vous le savez, retournez sur l'exemple précédent et essayez.

Encore une fois, le code à ajouter est très simple : rajouter un champ quickaction là où il n'y avait que des quicksearch. Vous pouvez spécifier une URL classique, mais aussi les champs « avancés », comme mailto:, tel: ou encore javascript:.

<tr quickaction="http://www.imdb.com/title/tt1586752/"
quicksearch="movie/status:notseen/Machine Gun Preacher">
<td>Machine Gun Preacher</td>
<td>The story of Sam Childers, a former drug-dealing biker tough guy who
found God and became a crusader for hundreds of Sudanese children who've been
forced to become soldiers.</td>
<td><img src="public/divers/red.png" title="Not seen" alt="no" /></td>
</tr>

Le petit plus

Enfin, essayez une dernière chose : entrez n’importe quoi dans le champ de recherche, suffisamment pour faire disparaitre tous les films. Et cette fois, appuyez de nouveau sur entrée. Quand quickaction ne trouve plus rien, il laisse la main au formulaire « classique » défini dans le HTML. Celui-ci est configuré pour aller chercher directement sur le moteur de recherche de l’IMDb.

Le concept est tout à fait améliorable j’en suis conscient, mais à l’usage il est déjà très agréable. Essayez ^^


Commentaires

1. Commentaire de Pierre777 le lundi 5 décembre 2011

Super article! Merci de partager


About the Author

Ted Marklor est un web designer, un web developer et un génie de la nature. Transcendant le web depuis bientôt 15 ans, Ted est une source d’inspiration et de conseil pour toute une génération de jeunes programmeurs. Le Web 2.0, c’est lui. Dans la vie, il aime aussi faire des avions en papier, s’inventer des pseudonymes et une vie de winner, et surtout parler de lui à la troisième personne. Ça se fait en ce moment sur les blogs…