Histoire d'un critère d'accessibilité de haut niveau (WCAG AAA) : l'apparence et la pertinence des liens en target="_blank",
plus connu comme Technique SCR24, partie procédure.
Théoriquement, il n'est pas obligatoire d'avoir un marqueur visuel d'ouverture d'un nouvel onglet ou d'une nouvelle fenêtre, ni de prévenir l'utilisateur.
Il n'en reste pas moins qu'il s'agit d'une bonne pratique, intéressante pour tout le monde.
Un des inconvénients est que ce n'est pas simple de fournir cette information avec les outils de contribution. Au mieux, on peut préciser avec une case à cocher que l'ouverture du lien va ouvrir une nouvelle fenêtre. Quant à ce qui est de la possibilité d'ajouter une classe CSS, à part faire du développement personnalisé, c'est souvent impossible.
L'idée est donc d'automatiser cette mise en forme.
Avantage pour les utilisateurs
Extrait du WCAG.
Les personnes qui sont incapables de détecter les changements de contexte ou qui ne se rendent peut-être pas compte que le contexte a changé sont moins susceptibles de devenir désorientées si elles initient elles-mêmes le changement.
Par exemple :
- Les personnes aveugles ou malvoyantes peuvent avoir des difficultés à savoir quand un changement de contexte visuel s'est produit, comme une nouvelle fenêtre qui apparaît. Dans ce cas, avertir les utilisateurs des changements de contexte à l'avance minimise la confusion lorsque l'utilisateur découvre que le bouton de retour ne se comporte plus comme prévu.
- Certaines personnes malvoyantes, ayant des déficiences de lecture et intellectuelles, et qui ont des difficultés à interpréter des indices visuels peuvent bénéficier d'indices supplémentaires afin de détecter les changements de contexte.
Le principe
Il va falloir détecter les liens concernés.
Le sélecteur 'a[target="_blank"]' va permettre de filtrer tout ça.
Le script intègre un filtre à adapter pour ne pas appliquer le pictogramme sur des liens particuliers. Par exemple, les liens ne contenant qu'une image, ou bien des liens déjà mis en forme par la feuille de styles.
Ensuite, il y a deux options :
- le lien n'a pas d'attribut
title: on insère "un élément" en CSS via::afterà la fin du lien, uniquement lu par les lecteurs d'écran. - le lien a un attribut
title: on ajoute l'information « ouverture dans une nouvelle fenêtre » à la suite de la valeur dutitle.
Et pour terminer, la feuille de styles va ajouter un pictogramme avant le lien.
Ce pictogramme sera évité par les lecteurs d'écran.
Il s'agit d'une proposition de script, à adapter éventuellement à votre environnement.
Javascript
Code à placer de préférence en bas de page pour ne pas impacter le CLS.
(() => {
/**
* Vérifie si un élément possède au moins une des classes spécifiées
* @param {Element} element - L'élément DOM à vérifier
* @param {string[]} classes - Tableau des classes à rechercher
* @returns {boolean} True si au moins une classe est présente
*/
if (typeof window.hasAnyClass !== 'function') {
window.hasAnyClass = (element, classes) => classes.some(cls => element.classList.contains(cls));
}
/**
* Gère l'ouverture des liens dans une nouvelle fenêtre et leur accessibilité
* Ajoute ou supprime les attributs target="_blank" et les indicateurs visuels/textuels
* selon la présence de la classe 'disable-blank' sur l'élément racine
*
* @param {Element|null} [fromDomNode=null] - Élément racine dans lequel chercher les liens.
* Si null, utilise document.body
* @global
*/
window.toggleBlank = (fromDomNode) => {
// Sortie anticipée pour les utilisateurs privilégiés, à adapter
if (hasAnyClass(document.body, ['admin', 'editor', 'moderator'])) return;
const t = (key, defaultValue) => typeof i18n !== 'undefined' && i18n[key] || defaultValue;
const wording = t('new_windows', ' (ouverture dans une nouvelle fenêtre)');
const isDisabled = document.documentElement.classList.contains('disable-blank');
const ignore = ['ratio-100', 'ratio', 'no-blank', 'wrap-image', 'blank'];
(fromDomNode || document.body).querySelectorAll('a[target="_blank"], a[data-set-target]').forEach((a) => {
a.rel ||= 'noreferrer';
if (isDisabled) {
a.dataset.setTarget = a.target || '';
a.removeAttribute('target');
if (a.title) {
a.title = a.title.replace(wording, '');
}
} else {
a.target = a.dataset.setTarget || '_blank';
if (!a.className || ![...a.classList].every(cls => ignore.includes(cls))) {
a.classList.add('js-blank');
}
if (a.title) {
a.title += ` ${wording}`;
}
}
});
};
})();
// appel de la fonction
toggleBlank();
Comme la fonction est rattachée à window, elle reste disponible pour l'appliquer à des éléments ajoutés dynamiquement dans la page (popin, contenu asynchrone, etc.).
La fonction utilise une constante globale i18n qui contient les traductions pour la langue courante.
/* Extrait (voir le source de la page) */
const i18n = {
JSON.parse(`"new_window": " (ouverture dans une nouvelle fen\u00eatre)"`)
};
Il y a un fallback dans la fonction, au cas où.
Feuille de styles
Le pictogramme est embarqué directement dans la feuille de styles. De cette manière, il hérite des couleurs des liens de la charte, grâce à la gestion par propriétés de mask.
:root {
/* pictogramme SVG */
--svg-newtab: url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">\
<path d="M29.28571,2.5H9.35714A2.23894,2.23894,0,0,0,7.14286,4.75V20.5a2.23894,2.23894,0,0,0,2.21428,2.25H29.28571A2.239,2.239,0,0,0,31.5,20.5V4.75A2.239,2.239,0,0,0,29.28571,2.5Zm0,18H9.35714V4.75H29.28571ZM18.21429,27.25h-15.5V16H4.92857V13.75H2.71429A2.239,2.239,0,0,0,.5,16V27.25A2.239,2.239,0,0,0,2.71429,29.5h15.5a2.239,2.239,0,0,0,2.21428-2.25V25H18.21429Z"/>\
</svg>');
}
:any-link[target="_blank"].js-blank:not(.no-blank)::before {
-webkit-mask-image: var(--svg-newtab);
-webkit-mask-size: 70%;
-webkit-mask-position: center center;
-webkit-mask-repeat: no-repeat;
mask-image: var(--svg-newtab);
mask-size: 70%;
mask-position: 0.125em center;
mask-repeat: no-repeat;
width: 1.75em;
display: inline-flex;
/* Espace insécable pour le visuel et fallback vide pour les lecteur d'écran */
content: "\A0" / "";
font-family: sans-serif;
font-size: 1em;
line-height: inherit;
background-color: currentColor;
vertical-align: baseline;
}
/* Gestion du message pour AT */
:any-link[target="_blank"].js-blank:not(.no-blank, [title])::after {
content: "" / ". Ouverture dans un nouvel onglet";
}
Résultat
Le code suivant
<a href="/" target="_blank">Aller à la page d'accueil</a>
affichera Aller à la page d'accueil, sans aucune autre intervention.
Le code interprété sera :
<a href="/" target="_blank" class="js-blank" rel="noreferrer">Aller à la page d'accueil</a>
Le bonus
Il n'est pas inutile de gérer une fonctionnalité qui permette de désactiver l'ouverture des liens en target="_blank".
Dans l'en-tête des pages, le pictogramme vous permet de visualiser la fonctionnalité.
That's all folks !