L'attribut hidden="until-found" a été ajouté pour améliorer l'accessibilité et le référencement des contenus en HTML, il permet de masquer du contenu tout en le laissant indexable par les moteurs de recherche et surtout trouvable via la fonction "Rechercher" du navigateur (raccourci Ctrl+F).
Le problème avec display: none
Habituellement, pour masquer un élément (tel que le contenu d'un accordéon ou d'un onglet), on utilise display: none (qui est très efficace et prévu pour cela) ou des hacks tels que les classes visually-hidden ou sr-only qui sont ajoutés "à la main" ou par des frameworks CSS tels que Bootstrap, Tailwind pour masquer du contenu visuellement sans toutefois empêcher son rendu par les lecteurs d'écran.
La difficulté avec cette approche est que le texte est effectivement invisible pour l'utilisateur mais aussi pour la fonction de recherche du navigateur. Si un utilisateur cherche un mot-clé présent dans un bloc masqué par défaut (de l'accordéon, ou d'un onglet inactif), il ne le trouvera jamais car ce texte restera inatteignable tant que le bloc n'est pas affiché à nouveau (ou déployé).
L'astuce hidden="until-found"
Lorsqu'on ajoute l'attribut hidden (qui existait déjà auparavant) avec cette nouvelle valeur until-found :
- Il est masqué par défaut (équivalent à
display: none). - Si l'utilisateur effectue une recherche (
Ctrl+F) et que le mot se trouve dans cette section, le navigateur révèle automatiquement l'élément. - Le navigateur déclenche un événement spécial appelé
beforematch.
Cas concret
<button onclick="toggleSection()">Afficher/Masquer les détails</button>
<div id="ma-section" hidden="until-found">
<p>Ce contenu est caché, mais si vous cherchez "raclette" avec Ctrl+F, il apparaîtra.</p>
</div>
Comment l'implémenter
Pour que cela fonctionne parfaitement, vous devez gérer l'aspect visuel lors de l'ouverture automatique et prendre en compte l'accessibilité.
Côté CSS
Le navigateur utilise l'état content-visibility: hidden pour cet attribut. Pour assurer une transition fluide ou un affichage correct, vous pouvez cibler l'élément quand il n'est plus caché avec :not([hidden]) et lui appliquer styles et animations/transitions.
Côté JavaScript
Si votre section est un accordéon avec une icône ou un style spécifique (bordure, couleur indiquant l'état ouvert/compacté), vous devez mettre à jour votre interface lorsque le navigateur trouve le texte avec l'événement beforematch, pour refléter ce changement.
const section = document.getElementById('ma-section');
section.addEventListener('beforematch', () => {
// Cette fonction s'exécute quand l'utilisateur "trouve" le texte caché
console.log("Le contenu a été révélé par une recherche.");
// Exemple : changer une classe CSS d'état
section.classList.add('is-open');
});
C'est accessible ? C'est supporté ?
En théorie sur le papier, oui, cette nouveauté est évidemment prévue et pensée pour ne pas être un frein à l'accessibilité numérique. Cependant tout est toujours lié à la façon dont vous allez écrire votre code, au support navigateur qui est tout frais pour certains d'entre eux (à ce jour les dernières versions de Firefox, Chrome, Safari, Edge le reconnaissent), et au support des lecteurs d'écran ou autres technologies d'assistance. L'avantage est qu'on se repose sur l'attribut hidden qui existe depuis un moment déjà, et qu'on ne fait que l'améliorer.
Autrement dit, si un ancien navigateur ne reconnaît pas la valeur until-found, la recherche Ctrl+F ne le trouvera pas, mais le fonctionnement de l'attribut hidden persiste, l'internaute peut toujours cliquer sur un bouton "Ouvrir" pour voir le contenu, mais le "super-pouvoir" de recherche est perdu.
Contrairement à display: none qui retire l'élément de l'arbre d'accessibilité (le rendant inexistant par exemple pour une synthèse vocale), hidden="until-found" se comporte de manière plus fine : le contenu est présent dans le DOM bien qu'il soit masqué visuellement, le navigateur sait qu'il est "trouvable" dans la page. Si un utilisateur de lecteur d'écran utilise la fonction de recherche de son outil, le navigateur révélera la section et placera le focus sur le texte trouvé. En revanche vous devez vous assurer que le contenu reste atteignable pour les personnes qui n'utiliseront pas la recherche, donc (par exemple) avec un bouton le révélant (mais ce n'est pas un problème car normalement c'est ce que vous souhaitez réaliser avec cet attribut).
Si vous l'utilisez pour un système d'accordéon, l'attribut aria-expanded doit passer de false à true au moment de la découverte. Sans un zeste de JavaScript pour mettre à jour les états ARIA lors de l'événement beforematch, l'utilisateur pourrait voir le contenu mais son outil d'assistance pourrait ne pas comprendre le changement d'état du composant parent.
👉 Vous ne devez pas compter uniquement sur cet attribut pour l'accès à l'information. Une bonne pratique pour un accordéon consisterait à :
- Utiliser un bouton standard pour ouvrir/fermer votre contenu (pour tous les navigateurs).
- Ajouter
hidden="until-found"pour offrir une expérience améliorée à ceux qui reconnaissent cette valeur. - Utiliser l'événement
beforematchpour synchroniser vos états JavaScript, et par exemple en profiter pour ajouter l'état ARIAaria-expanded="true"
element.addEventListener('beforematch', () => {
button.setAttribute('aria-expanded', 'true');
});
Le récapitulatif
| Attribut / Valeur | Invisible ? | Trouvable via Ctrl+F ? | SEO Friendly ? |
|---|---|---|---|
hidden (classique) |
Oui | Non | Moyen bof |
display: none |
Oui | Non | Très peu |
hidden="until-found" |
Oui | Oui | Prévu ! |
Quand l'utiliser ?
- Accordéons / système de FAQ : Pour que les réponses soient "trouvables" sans ouvrir chaque section individuellement.
- Menus "Lire la suite" : Pour ne pas pénaliser le SEO sur de longs textes tronqués.
- Systèmes d'onglets : Pour permettre la recherche dans tous les onglets inactifs.
Sympa non ?
Commentaires
Très intéressant, je ne connaissais pas cette valeur de l'attribut hidden, donc merci pour cet article.