Courant Mis à jour : 2025-05

SVG et icônes : les cas complexes

Les quatre cas à distinguer pour les SVG inline et les icônes : décoratif, informatif seul, dans un lien avec texte, dans un lien sans texte. Font Awesome, sprites SVG, et les erreurs fréquentes.

Table des matières

Les SVG inline et les font-icons posent des problèmes d’accessibilité différents des balises <img> classiques. Ils n’ont pas d’attribut alt natif, leur comportement avec les technologies d’assistance (AT) varie selon la méthode d’implémentation, et leur contexte d’utilisation détermine entièrement ce qu’il faut faire.

Quatre cas couvrent 95% des situations rencontrées en audit.

Les quatre cas à distinguer

Cas 1 : Icône décorative dans un élément qui a déjà un label

C’est le cas le plus courant. Une icône accompagne du texte ou un élément labellisé — elle ne porte aucune information propre.

<!-- Icône dans un bouton avec texte visible -->
<button>
  <svg aria-hidden="true" focusable="false">
    <use href="#icon-enveloppe"/>
  </svg>
  Envoyer le message
</button>

<!-- Icône dans un lien avec texte visible -->
<a href="/mairie">
  <svg aria-hidden="true" focusable="false">
    <use href="#icon-mairie"/>
  </svg>
  Mairie
</a>

<!-- Icône dans un label de champ -->
<label for="email">
  <svg aria-hidden="true" focusable="false">
    <use href="#icon-mail"/>
  </svg>
  Adresse email
</label>

aria-hidden="true" : masque le SVG à l’arbre d’accessibilité. Les AT l’ignorent complètement.

focusable="false" : empêche certains navigateurs anciens (Internet Explorer, Edge Legacy) de rendre le SVG focusable via Tab. Sans cet attribut, l’utilisateur peut “tomber” sur un SVG vide dans sa navigation clavier.

Ce qu’on ne fait pas ici : role="img", aria-label, <title>, car tout cela serait redondant avec le texte adjacent.

Cas 2 : Icône seule, porteuse de l’information

L’icône est le seul contenu d’un élément interactif, ou elle porte une information non disponible dans le texte adjacent.

SVG seul dans un bouton ou un lien

<!-- ✗ NC — aucune alternative textuelle -->
<button>
  <svg aria-hidden="true" focusable="false">
    <use href="#icon-fermer"/>
  </svg>
</button>

<!-- ✓ Option A — aria-label sur le bouton/lien -->
<button aria-label="Fermer la fenêtre">
  <svg aria-hidden="true" focusable="false">
    <use href="#icon-fermer"/>
  </svg>
</button>

<!-- ✓ Option B — texte sr-only dans le bouton -->
<button>
  <svg aria-hidden="true" focusable="false">
    <use href="#icon-fermer"/>
  </svg>
  <span class="sr-only">Fermer la fenêtre</span>
</button>

Pourquoi l’option B est souvent préférable : le texte sr-only est traduit par les outils de traduction automatique (Google Translate). L’aria-label ne l’est pas toujours, selon les navigateurs et les versions. Sur un site de commune avec des visiteurs internationaux, par exemple, c’est un argument.

SVG informatif hors élément interactif

<!-- SVG qui transmet une information seul dans le contenu -->

<!-- ✗ NC -->
<svg aria-hidden="true" focusable="false">
  <use href="#icon-alerte"/>
</svg>
Votre session va expirer.

<!-- ✓ role="img" + aria-label sur le SVG -->
<svg role="img" aria-label="Avertissement" focusable="false">
  <use href="#icon-alerte"/>
</svg>
Votre session va expirer.

<!-- ✓ Ou texte sr-only adjacent -->
<span class="sr-only">Avertissement : </span>
<svg aria-hidden="true" focusable="false">
  <use href="#icon-alerte"/>
</svg>
Votre session va expirer.

Cas 3 : SVG inline complexe (graphique, diagramme, carte)

Un SVG qui constitue à lui seul une image informative, comme un graphique de données, une carte géographique, ou encore un schéma.

<!-- ✓ role="img" + aria-labelledby vers un <title> interne -->
<svg role="img" aria-labelledby="titre-graphique" focusable="false">
  <title id="titre-graphique">
    Répartition du budget 2025 : voirie 40 %, social 30 %, culture 20 %, administration 10 %
  </title>
  <!-- paths du graphique -->
</svg>

<title> dans le SVG, c’est l’équivalent de l’alt pour un SVG inline. aria-labelledby pointe vers cet élément pour que les AT l’utilisent comme nom accessible.

Pour les SVG complexes : si le contenu est trop riche pour un <title> court, ajouter un <desc> pour la description longue, et aria-describedby en complément :

<svg role="img"
  aria-labelledby="titre-carte"
  aria-describedby="desc-carte"
  focusable="false">
  <title id="titre-carte">Carte des zones de collecte</title>
  <desc id="desc-carte">
    La commune est divisée en 3 zones :
    zone nord (quartier du port), zone centre (bourg),
    zone sud (hameau de Feoja). 
    Collecte le mardi pour les zones nord et centre, le jeudi pour la zone sud.
  </desc>
  <!-- paths de la carte -->
</svg>

Cas 4 : Font Awesome et autres font-icons

Les font-icons (Font Awesome, Material Icons, Dashicons dans WordPress) insèrent leurs icônes via des caractères Unicode dans la zone d’usage privé, à l’intérieur d’un <span> ou d’un <i> vide.

Le comportement AT est imprévisible : certains lecteurs d’écran annoncent un caractère parasite, d’autres ignorent, d’autres encore annoncent le nom CSS de la classe. Aucun de ces comportements n’est contrôlable sans intervention explicite.

Pour une icône décorative :

<!-- ✓ Font Awesome — icône décorative -->
<span class="fa fa-envelope" aria-hidden="true"></span>
Nous contacter

Pour une icône porteuse d’information seule :

<!-- ✗ NC — aucune alternative -->
<a href="/contact">
  <span class="fa fa-envelope"></span>
</a>

<!-- ✓ Option A — aria-label sur le lien -->
<a href="/contact" aria-label="Nous contacter par email">
  <span class="fa fa-envelope" aria-hidden="true"></span>
</a>

<!-- ✓ Option B — texte sr-only dans le lien -->
<a href="/contact">
  <span class="fa fa-envelope" aria-hidden="true"></span>
  <span class="sr-only">Nous contacter par email</span>
</a>

Les sprites SVG : <use> et le piège du shadow DOM

Les sprites SVG utilisent <use href="#icon-id"> pour référencer un symbole défini ailleurs dans le DOM ou dans un fichier externe. Un problème fréquent : le <title> défini dans le symbole source n’est pas toujours exposé à l’arbre d’accessibilité quand il est instancié via <use>.

<!-- Définition du symbole -->
<svg style="display:none">
  <symbol id="icon-alerte" viewBox="0 0 24 24">
    <title>Alerte</title>
    <path d="..."/>
  </symbol>
</svg>

<!-- Usage — le <title> peut ne pas être annoncé selon le navigateur -->
<svg>
  <use href="#icon-alerte"/>
</svg>

Solution robuste : toujours déclarer l’alternative sur l’élément <svg> parent, pas dans le symbole :

<!-- ✓ Alternative sur le svg parent -->
<svg role="img" aria-label="Alerte" focusable="false">
  <use href="#icon-alerte"/>
</svg>

<!-- ✓ Ou masquer complètement si décoratif -->
<svg aria-hidden="true" focusable="false">
  <use href="#icon-alerte"/>
</svg>

Erreurs fréquentes

role="img" sans aria-label: crée une image sans alternative. NVDA annonce “graphique” sans description.

<!-- ✗ role="img" sans label -->
<svg role="img">...</svg>

<!-- ✓ -->
<svg role="img" aria-label="Description de l'image">...</svg>

aria-label sur le SVG ET texte visible dans le lien : double annonce.

<!-- ✗ "Mairie" sera annoncé deux fois -->
<a href="/mairie">
  <svg aria-label="Mairie">...</svg>
  Mairie
</a>

<!-- ✓ L'icône est décorative, le texte suffit -->
<a href="/mairie">
  <svg aria-hidden="true" focusable="false">...</svg>
  Mairie
</a>

Font Awesome sans aria-hidden dans un bouton ou lien : le span vide peut être annoncé.

<!-- ✗ Comportement imprévisible selon l'AT -->
<button>
  <i class="fas fa-download"></i>
  Télécharger
</button>

<!-- ✓ -->
<button>
  <i class="fas fa-download" aria-hidden="true"></i>
  Télécharger
</button>

focusable="false" absent sur SVG : rare sur les navigateurs modernes, mais prudent de toujours l’inclure.

Récapitulatif : Quel attribut selon le cas

SituationSolution
SVG décoratif dans un élément labelliséaria-hidden="true" focusable="false"
SVG seul dans un bouton/lienaria-hidden sur le SVG + aria-label sur le bouton ou span.sr-only
SVG informatif seul dans le contenurole="img" aria-label="..."
SVG complexe (graphique, carte)role="img" aria-labelledby<title> interne
Font-icon décorativearia-hidden="true" sur le <span>
Font-icon seule dans un lienaria-hidden sur l’icône + aria-label sur le lien ou span.sr-only

Critères RGAA : 1.1 (alternatives textuelles), 1.2 (images décoratives), 6.1 (intitulés des liens).

La lettre de l'Atelier A11Y

Ressources pédagogiques, critères RGAA commentés et retours de terrain : une lettre mensuelle pour progresser sur l'accessibilité numérique, sans jargon.

  • Nouveaux articles et ressources pédagogiques
  • Critères RGAA décortiqués avec des exemples concrets
  • Bonnes pratiques et retours d'expérience terrain
S'abonner à la newsletter (s'ouvre dans un nouvel onglet)

Gratuit. Désabonnement possible à tout moment.