Les picto fontes ou comment se simplifier la gestion des icones

Les icônes sur le web en 2012, une vraie galère

Ces petits éléments graphiques si chers à nos design sont essentiels, s'ils sont bien choisis ils apportent beauté et compréhension à l'expérience utilisateur de l'internaute. Le hic c'est qu'il est compliqué de les gérer pour un webmaster. Problèmes de résolutions d'écrans, de tailles, de couleurs, etc. Il faut sans cesse changer tel ou tel icone à tel ou tel endroit du site parce que tel autre picto ferait mieux l'affaire... Alors oui il y a bien les sprites css pour nous sauver la mise, cette technique consiste à mettre tous les pictos côte-à-côte dans une seule image puis d'assigner leur background-position x et y à des classes css qui sont elles-même ensuite appliquées aux éléments html de la page. Ainsi une balise <a class="icon-share"> aura son image de background positionnée pile sur la zone qui montre le picto "share". On peut ensuite changer la classe css par une autre pour afficher une autre icône, exemple : <a class="icon-search"> pour afficher une loupe, etc. Twitter Bootstrap dispose d'une bibliothèque d'icônes toute prête avec des classes css à placer sur vos balises html. De plus avec un bon générateur de sprite on peut encore un peu plus se faciliter la tâche. Personnellement j'aime faire mes sprites à la main dans Photoshop... je sais pas, ça me détend :P

Bon donc les sprites c'est top. Sauf que ça se corse quand le design implique de gérer nos icônes en plusieurs tailles voir même en plusieurs couleurs... Alors là, ça devient carrément un massacre si on commence à gérer autant de sprite qu'on a de tailles et/ou couleurs... je vous laisse imaginer le cauchemar. Sans parler des icônes récupérées sur le net qu'on ne possède qu'en une seule taille, souvent trop petite puisque toujours en 72dpi. Et bien sûr l'arrivée des écrans Rétina (ou HD) rend la tâche encore un peu plus ardue.

Les pictos fonts à la rescousse

Exemple de glyphe icônes gérées via css à un instant T

Avec d'autres css

Alors là c'est le must ! En fait le principe est d'utiliser une police (une font en anglais) dont chaque lettre représente une icône. Première chose à savoir, les icônes utilisées sont vectorielles (pas en pixel donc agrandissables à l'infini) on se débarrasse ainsi du problème posé par les écrans Retina d'Apple (iPad 3, MacBook Pro 2012) et leur densité de pixel outrageusement élevée par rapport aux écrans du marché actuel. Sur les images ci-contre la taille, la couleur et la disposition des icônes sont gérés via css uniquement !

Le vectoriel implique aussi de trouver des icônes vectorisées sur le net, et oui ça devient payant puisqu'on touche aux droits d'auteurs (là on parle d'obtenir les sources, souvent en illustrator, d'icônes faite par des designers dont c'est le gagne-pain). IconFinder et compagnie deviennent pour le coup quasiment inutiles, on n'y trouve que des pictos au format png en 16x16px. Ça changera peut-être avec le temps, attendons que plus de designers talentueux se mettent à partager des packs d'icônes vectorielles gratuits au nom de l'Open Source.

Ce n'est à proprement parler pas facile de se confectionner sa propre fonte. Il faut passer par un logiciel comme FontForge ou autres que je ne connais pas. Mais partant de ce postulat, de talentueux développeurs se mettent à pondre des solutions "clé-en-main" pour générer ces pictos fonts via leur outil online gratuit ou payant.

L'idée est de composer son propre pack d'icônes puis de choisir à quelles lettres de l'alphabet on souhaite lier chaque picto puis on click sur un bouton qui génère le tout. Cool ! IcoMoon permet même d'uploader ses propres icônes sur leur site.

Le vecteur confère aux picto fonts des avantages considérables puisqu'on peut donc changer la taille de l'icône à sa guise uniquement en changeant font-size et viens s'ajouter d'autres propriétés css très utiles comme color ou text-shadow... Eh oui, nos icônes sont maintenant considérées comme du texte par le navigateur ! L'administration est entièrement confiée à la feuille de style du site et... ça fait du bien :)

Voici un exemple, mettons qu'on a une icône de loupe (destinée à un formulaire de recherche) et que c'est la lettre "s" qui lui soit attribuée. Et qu'au même titre que l'Arial s'appelle l'Arial eh bien notre custom fonte s'appelle 'myAwesomeFont', voici comment ça s'utilise :

# css
.icon { font-family: 'myAwesomeFont'; }

# html
<span class="icon"> s </span>

Ou alors une variante que j'aime moins :

# css
.icon { font-family: 'myAwesomeFont'; }
[data-icon]:before { content: attr(data-icon); }

# html
<span class="icon" data-icon="s"></span>

Ici on utilise l'attribut data-icon pour y mettre la lettre de l'alphabet puis en css avec la pseudo classe :before on récupère la valeur de data-icon pour la passer dans la propriété content du :before en question. C'est mignon comme technique mais c'est quand-même un peu de la frime hein :P

Bon et l'accessibilité dans tout ça ?

C'était bien là le soucis justement. Comment rendre cette technique suffisemment accessible... parce qu'avoir un balise qui ne contient qu'une simple lettre c'est pas franchement le top.

Du coup, utiliser le :before pour y mettre l'icône n'est finalement plus si bête. Et si on combine ça avec un dérivé de la technique surannée du sprite :P ça donne un truc vraiment pas mal :

# css
[class^="icon-"]:before, 
[class*=" icon-"]:before { 
  font-family: 'myAwesomeFont'; 
  speak: none;
}
.icon-phone:before  { content:"a"; }
.icon-mobile:before { content:"b"; }
.icon-mouse:before  { content:"c"; }

# html
<a class="icon-phone">Business phone</a>
<a class="icon-mobile">Personal phone</a>
<a class="icon-mouse">Email address</a>

Ici on commence par attribuer notre font-family 'myAwesomeFont' à tous les éléments html dont la classe css commence par "icon-" (class^="icon-") ou bien à tous les éléments html dont la classe css contient " icon-" (class*=" icon-"). Puis on attribue les lettres de la fonte à des classes css intelligemment nommées. Et le tout se passe au niveau des :before.

UPDATE 29/10/12
Il se trouve que malheureusement les screen readers vont lire la lettre associée à l'icône.

Cas concret :
- User pense : "tiens j'ai envie de savoir de quoi ça s'agit".
- Le User appuie sur tab et se retrouve en focus sur notre lien icon-phone, rappelez-vous qu'il est associé à la lettre "a" dans notre fonte (voir l'exemple juste au-dessus).
- ScreenReader dit d'une voie mécanique : "Link", "A", "Business phone".
- User dit : "gnié c'était quoi ce A ???"

Pour éviter ce désagrément icomoon permet (au moment de la génération) d'associer nos icône aux caractères de la Private Use Area (PUA). Les screen reader ne comprennent pas l'encodage des caractères présents dans cette partie d'Unicode. Et au final ça donne ça :

[class^="icon-"]:before, 
[class*=" icon-"]:before { 
  font-family: 'myAwesomeFont'; 
  speak: none;
}
.icon-phone:before  { content:"\e000"; }
.icon-mobile:before { content:"\e001"; }
.icon-mouse:before  { content:"\e002"; }

C'est un peu moins intuitif que de choisir soi-même les lettres de l'alphabet mais au moins ça rend cette technique accessible ce qui n'est pas rien. Le speak none est rajouté par Icomoon au moment de la génération et je n'ai pas confirmé que ça servait effectivement à quelque chose même si on se doute de ce qu'il est censé faire. Je me contente de le laisser.

Et niveau compatibilité navigateurs on est comment ?

Si on laisse tel quel on est pas extraordinairement compatible. En premier lieu, :before n'est qu'ie8+ donc on fait dors-et-déjà le choix de ne pas supporter ie7 puis vient le problème de l'utilisation d'une custom fonte. On sait que @font-face s'impose mais cette propriété est comment dire... touchy si on veut vraiment que notre fonte marche partout. En fait les navigateurs ne supportent pas tous la même chose... L'idéal est d'avoir 5 formats différents pour n'oublier personne :

@font-face {
  font-family: 'MyAwesomeFont';
  src:url('myfont.eot'); /*ie9 compat modes*/
  src:url('myfont.eot?iefix') format('eot'), /*ie6-ie8*/
      url('myfont.woff') format('woff'), /*modern browsers*/
      url('myfont.ttf')  format('truetype'), /*safari,android,iOS*/
      url('myfont.svg#svgFontName') format('svg'); /*legacy iOS*/
}

Fort heureusement, les outils comme IcoMoon (et d'autres gratuits arriveront bientôt j'en suis sûr) génèrent toutes les variantes de fonte nécessaires ainsi que le css qui va avec pour vous mâcher le travail.

Conclusion

Clairement cette technique risque de s'imposer pour remplacer notre traditionnel sprite.png, au moins le temps que des support comme SVG soit plus vastement supportés.

En tout cas, une fois qu'on a tout ça (des icônes vectorielles, des webfonts tous navigateurs et les css vus plus hauts) eh bien on peut administrer nos icônes via css tout en respectant les normes d'accessibilité, avec des icônes de bonne qualité quelque soit la définition de l'écran et le tout compatible ie8+ s'il vous plaît ! Olé !

Liens utiles

IcoMoon pour générer, stocker, modifier vos pictos fonts
Fontello idem qu'icoMoon
Pictos idem qu'icoMoon mais en payant
• Apprendre à se servir des sprites css : A List Apart et CSS Tricks
Goetter abordant l'accessibilité de manière un peu plus poussée
Suggestions pour améliorer l'accessibilité
Chris Coyer montrant tous les avantages des pictos fonts

Be Sociable, Share!

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>