CSS Highlight API : peinture et accessibilité
Utilisez des surbrillances personnalisées avec texte sémantique, plages bornées, focus clavier, contraste et repli accessible.
BotBrowser Team
Vous voulez la documentation structurée pour Plateforme ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
CSS Highlight API peut styliser les correspondances de recherche, les annotations et les sélections sans modifier le DOM, mais un surlignage est une présentation, pas un sens. BotBrowser peut rejouer un fixture de surlignage appartenant à la page et inspecter les replis visibles ; il ne peut pas certifier la parole d’une technologie d’assistance, l’intention de lecture d’une personne ni l’implémentation complète du rendu du navigateur. Gardez le contrat étroit : exposez le texte dans le DOM, enregistrez des plages bornées, peignez une couche distincte et conservez un repli sémantique utilisable au clavier.
TL;DR
CSS.highlights.set('search-hit', new Highlight(range))applique un style à unRange; il n’ajoute ni texte, ni libellé, ni sémantique accessible.- Un pseudo-élément de surlignage comme
::highlight(search-hit)doit utiliser une paire de couleurs au contraste sûr et ne jamais être l’unique indice. - Gardez le texte source et un compteur de résultats annoncé dans le DOM ; testez séparément le focus clavier, la sélection, les couleurs forcées, le zoom et la réduction des mouvements.
- Reconstruisez les plages après les changements de contenu, limitez leur nombre et leur longueur, puis supprimez les entrées obsolètes avec
CSS.highlights.delete(name). - BotBrowser peut vérifier l’état propre à la page et le repli ; les recommandations viennent des sources et aucune exécution BotBrowser n’est déclarée.
Sommaire
- Garder le sens dans le DOM
- Enregistrer des plages bornées
- Peindre une couche visible et accessible
- Gérer la sélection, le focus et le repli
- Classer les résultats avec une table de décision
- Capacité et limites de BotBrowser
- Conclusion pratique
Garder le sens dans le DOM
L’API de surlignage change la façon dont le texte existant est peint. Un Range pointe vers des nœuds déjà présents ; un lecteur d’écran, une copie, une recherche textuelle et un rendu sans CSS ont donc besoin du même contenu source. Placez le compteur de résultats dans une région aria-live="polite", gardez la requête dans un champ libellé et exposez une liste ou un paragraphe ordinaire pour les annotations. N’encodez pas un avertissement uniquement avec un fond jaune ou un effet de peinture personnalisé.
L’API est distincte de la Selection API. Une sélection utilisateur peut être visible via ::selection ; un surlignage personnalisé nommé est un objet Highlight géré par l’application. Donnez à chaque état un nom stable comme search-hit ou current-hit et supprimez-le lorsque la requête est vide. Le nom est un hook CSS, pas un libellé qu’une technologie d’assistance annoncera.
Pour une limite connexe de l’identité visuelle, gestion des couleurs CSS et accessibilité de l’affichage explique comment séparer un résultat de style visible dans le navigateur d’une revendication de capacité. Pour l’interaction clavier, paramètres régionaux et confidentialité de Keyboard Layout API montre pourquoi un libellé visuel ne doit pas devenir une inférence sur la personne qui l’utilise. La revue de compatibilité des Web Components ajoute une matrice qui sépare détection de fonction et promesse faite au lecteur.
Enregistrer des plages bornées
Créez les plages à partir des nœuds de texte rendus, pas d’une chaîne HTML non fiable. Un fixture simple peut parcourir les nœuds de texte, trouver une requête insensible à la casse et appeler range.setStart() et range.setEnd() pour chaque correspondance. Limitez MAX_HIGHLIGHTS et MAX_MATCH_CHARS ; la page doit rester réactive lorsqu’une requête correspond à des milliers de mots.
const MAX_HIGHLIGHTS = 100;
const MAX_MATCH_CHARS = 120;
function showMatches(root, query) {
CSS.highlights.delete('search-hit');
if (!query || !window.Highlight) return 0;
const ranges = [];
for (const node of root.querySelectorAll('[data-search-text]')) {
const text = node.textContent || '';
let offset = 0;
while (offset < text.length && ranges.length < MAX_HIGHLIGHTS) {
const start = text.toLocaleLowerCase().indexOf(query.toLocaleLowerCase(), offset);
if (start < 0) break;
if (query.length <= MAX_MATCH_CHARS) {
const range = new Range();
range.setStart(node.firstChild, start);
range.setEnd(node.firstChild, start + query.length);
ranges.push(range);
}
offset = start + Math.max(query.length, 1);
}
}
CSS.highlights.set('search-hit', new Highlight(...ranges));
return ranges.length;
}
Le fixture exact dépend des limites des nœuds de texte ; le code de production doit gérer sans risque les nœuds imbriqués et un firstChild vide. Recalculez après le rendu, la localisation, le filtrage ou le recyclage d’une liste virtuelle. Une plage qui pointe vers du contenu supprimé est un état obsolète, pas une raison de conserver un ancien objet de surlignage.
Peindre une couche visible et accessible
Utilisez le pseudo-élément ::highlight(search-hit) pour la couche nommée et gardez des déclarations courtes. Le style de CSS Highlight API est volontairement limité par rapport aux éléments ordinaires ; le navigateur peut ignorer les propriétés non prises en charge. Choisissez un premier plan et un arrière-plan qui atteignent la cible de contraste du produit, puis ajoutez un indice non chromatique, comme un contour, une icône ou un compteur dans l’interface voisine.
::highlight(search-hit) {
color: #111827;
background-color: #fde68a;
text-decoration: underline 0.12em solid #92400e;
}
@media (forced-colors: active) {
::highlight(search-hit) {
color: CanvasText;
background-color: Highlight;
text-decoration: underline;
}
}
Ne supposez pas qu’un surlignage personnalisé est peint de façon identique dans chaque moteur ou contexte intégré. Détectez CSS.highlights, Highlight et le sélecteur utilisé, puis affichez la classe de repli ou le marqueur en ligne si un prérequis manque. Un résultat de peinture visible dans le navigateur ne prouve pas qu’un lecteur d’écran annoncera « correspondance » ni qu’un mode à contraste élevé conservera vos couleurs.
Gérer la sélection, le focus et le repli
La recherche doit déplacer le focus vers un vrai contrôle de résultat, pas vers une plage peinte. Fournissez des boutons Précédent et Suivant dotés d’un nom accessible, conservez la requête dans le champ et faites défiler le résultat sélectionné sans piéger le focus clavier. Si l’utilisateur sélectionne du texte, ne remplacez pas ::selection par le surlignage de recherche ; les deux couches expriment des états différents.
Lorsque les surlignages ne sont pas pris en charge, ajoutez un élément mark temporaire ou une classe CSS autour d’un nœud de texte fiable et exposez le même compteur et la même navigation. Supprimez ce repli avant d’appliquer une nouvelle requête afin d’éviter l’accumulation d’enveloppes imbriquées. Pour les annotations en lecture seule, une note adjacente avec aria-describedby est plus sûre qu’un patch de couleur qui disparaît à l’impression ou en mode couleurs forcées.
Vérifiez le zoom à 200 %, l’espacement du texte, la navigation au clavier seul, prefers-reduced-motion et un lecteur d’écran. Le surlignage ne doit pas masquer les contours du focus, couper les jambages descendants ni créer une animation qui clignote pour chaque résultat. Si la requête est vide ou sans correspondance, effacez le surlignage nommé et annoncez « 0 résultat » dans la région active.
Classer les résultats avec une table de décision
| Observed stage | What it establishes | Safe next action |
|---|---|---|
CSS.highlights or Highlight absent | Named highlights cannot start in this context | Use semantic mark or plain text and keep navigation usable |
| API present, query empty | There is no range to paint | Delete search-hit, announce the cleared state, and retain focus |
| Ranges created, paint visible | The page applied one browser-visible style layer | Verify contrast, focus, forced colors, and accessible result text |
| Content or locale changed | Existing offsets may be stale | Rebuild ranges from current text nodes and discard the old object |
| Match count exceeds 100 | The fixture hit its bounded workload | Show a capped result state and offer narrower search, not unbounded work |
| Forced colors or print differs | Presentation changed by user agent or medium | Keep the DOM result and a non-color cue as the source of meaning |
Chaque ligne décrit une condition observable, pas une promesse universelle. Notez l’état visible, la longueur de la requête, le nombre de plages et le repli choisi ; ne conservez pas le document entier et n’inférez pas le comportement de lecture.
| Point de contrôle | Trace | Ce que cela ne prouve pas |
|---|---|---|
| Détection API | CSS.highlights=true, Highlight=true | La parole d’un lecteur d’écran |
| Cycle de plage | rangeCount=3, longueur et nœuds | Une identité liée au texte |
| Repli | fallback=mark et raison | Une panne générale d’accessibilité |
| Focus | focusTarget=result-2 et ordre clavier | L’intention de la personne |
| Nettoyage | ancien surlignage supprimé | La suppression d’un état distant |
| Vérification | Trace minimale | Ne pas déduire |
|---|---|---|
| Compatibilité API | window.CSS, CSS.highlights, window.Highlight | Que toutes les propriétés CSS sont prises en charge |
| Limites de requête | MAX_HIGHLIGHTS=100, MAX_MATCH_CHARS=120 | Que le document entier peut être conservé |
| Plage actuelle | nœud source et rangeCount | Que le texte soit lié à une identité |
| Focus | focusTarget=result-2 | Que la personne souhaite lire ce résultat |
| Mode visuel | normal, couleurs forcées ou impression | Que l’écran physique utilise les mêmes couleurs |
| Nettoyage | nom supprimé avant un nouveau rendu | Qu’un état distant a été supprimé |
Capacité et limites de BotBrowser
BotBrowser peut exécuter un fixture de page autorisé et vérifier le compteur DOM, le nombre de plages et le chemin de repli. Il ne peut pas certifier la lecture par un lecteur d’écran ni garantir que chaque moteur peigne ::highlight() de la même façon.
BotBrowser peut rejouer un fixture autorisé qui enregistre des plages Highlight, applique ::highlight() et vérifie le repli visible ; les recommandations viennent des sources et aucune exécution BotBrowser n’est déclarée, pas plus qu’une certification de la parole d’un lecteur d’écran ou de la perception des couleurs.
{
"api": "CSS.highlights",
"highlightName": "search-hit",
"rangeCount": 3,
"maxHighlights": 100,
"domResultText": "3 matches",
"assistiveTechnologySpeech": "not-asserted"
}
Répétez le fixture après une version du navigateur, un changement de localisation, une liste virtuelle ou un nouveau token de contraste. Comparez la première différence visible et conservez le repli DOM dans le dossier d’acceptation.
Sources publiques
- CSS Custom Highlight API specification
- MDN: CSS Custom Highlight API
- MDN: ::highlight()
- BotBrowser advanced features
Conclusion pratique
Utilisez la peinture personnalisée de CSS Highlight API pour souligner un texte qui porte déjà un sens sémantique. Bornez et reconstruisez les plages, gardez l’état et la navigation dans le DOM et fournissez un repli sans couleur au contraste sûr. Considérez la sortie BotBrowser comme une preuve du comportement de la page, pas comme une preuve de parole assistive ni de l’interprétation d’une personne.
BotBrowser peut rejouer un fixture autorisé qui enregistre des plages Highlight, applique ::highlight() et vérifie le repli visible ; cet article ne revendique aucune exécution BotBrowser et ne certifie ni la parole d’un lecteur d’écran ni la perception des couleurs.
Cet article fait partie du guide : Surfaces de la plateforme web : carte de revue
Articles Connexes
Gestion des couleurs CSS et accessibilité de l’affichage
PlateformePréférences des media queries : respecter les choix des utilisateurs
PlateformeView Transitions API : état et navigation
PlateformeRevue de compatibilité navigateur pour les Web Components
PlateformeVoix de synthèse vocale et lecture accessible dans le navigateur
PlateformePopover API : focus, fermeture et accessibilité
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.