text-spacing-content-loss

Le texte reste lisible lorsque l’utilisateur augmente l’espacement du texte

automaticWCAG 1.4.12 (AA)confiance : mediumgravité : seriousperceivable

Applique l’espacement du texte de WCAG 1.4.12 dans le navigateur et vérifie qu’aucun texte n’est coupé ni amené à se chevaucher, et pose la question pour les règles de feuille de style qui imposent l’espacement avec !important.

Applicabilité. S’applique à une page contenant du texte visible. La perte de contenu nécessite une mise en page (un navigateur) : sans elle, seules les feuilles de style sont lues.

Attendu. WCAG 1.4.12 : avec une hauteur de ligne de 1,5 fois la taille de police, un espacement après les paragraphes de 2 fois, un espacement des lettres de 0,12 fois et un espacement des mots de 0,16 fois, aucun contenu ni aucune fonctionnalité n’est perdu.

  • Dans un navigateur, l’espacement est appliqué au moyen d’une feuille de style qui l’emporte sur celle de la page (sauf !important en ligne, que signale avoid-inline-spacing), et chaque ligne de texte est mesurée avant et après par rapport aux boîtes qui la découpent : celles de sa chaîne de blocs conteneurs qui ont overflow: hidden ou clip, ou contain: paint, et le viewport sur un axe que la page empêche de défiler, ou pour un texte dans une boîte fixe, qui ne défile pas avec la page. Une ligne qui était à l’intérieur et finit au moins à moitié à l’extérieur (la moitié de sa hauteur, ou une demi-em en largeur) échoue : le conteneur coupe ce texte (TEXT_CLIPPED). Une ligne repoussée de moins donne lieu à une question (TEXT_CLIPPED_PARTLY), tout comme un texte qui se met à chevaucher un autre texte qu’il ne chevauchait pas avant (TEXT_OVERLAPS). Un texte déplacé par une animation qui se répète indéfiniment (un bandeau défilant) donne lieu à une question quelle que soit la distance parcourue (TEXT_CLIPPED_MOVING) : il franchit le bord de toute façon, et une seule image ne permet pas de dire si une partie en est perdue. Lorsque le défilement de la page est verrouillé, les deux axes du viewport masqués alors que du contenu se trouvait déjà au-delà, comme derrière un bandeau de cookies, un texte que l’espacement fait sortir du viewport donne lieu à une question (VIEWPORT_SCROLL_LOCKED) : le verrouillage est généralement un état passager, et le moteur ne peut pas voir au-delà. Le texte situé dans un <marquee> est laissé de côté : les navigateurs le déplacent en dehors de la Web Animations API, de sorte que le moteur ne peut pas le figer, et son constat dépendrait du moment où l’analyse a eu lieu ; deprecated-elements-not-used pose la question du marquee (2.2.2). Un texte que sa boîte coupait déjà avant l’espacement (un extrait de hauteur fixe) donne lieu à une question lorsque l’espacement coupe des lignes qu’il montrait en entier (TEXT_CLIPPED_FURTHER) : l’extrait était coupé volontairement, mais il en montre moins. Une boîte qui grandit avec ses lignes, comme le fait line-clamp, en montre autant et n’est pas examinée.
  • Dans tout environnement, une règle de feuille de style qui fixe line-height, letter-spacing ou word-spacing en dessous de ces valeurs avec !important donne lieu à une question (STYLESHEET_IMPORTANT) : un outil qui ajoute sa propre feuille de style à la page ne peut pas la remplacer, alors qu’une feuille de style utilisateur le peut. Une valeur relative à la taille de police est lue telle que déclarée, et une valeur calculée atteint le minimum à l’arrondi près avec lequel les navigateurs indiquent les longueurs : une règle qui fixe exactement le minimum ne donne donc pas lieu à une question.
  • L’espacement est appliqué au moyen d’un élément <style> ou, lorsque la Content Security Policy de la page le bloque, d’une feuille de style adoptée par le document. Lorsqu’aucun des deux ne s’applique, la page donne lieu à une question (SPACING_NOT_APPLIED) au lieu d’être mesurée, et n’est jamais considérée comme réussie.

Sans mise en page et sans règle de ce type, la règle est notApplicable, avec data.reason: 'noLayout'.

  • Seul le texte situé dans le périmètre de l’analyse (contextSelector) et non exclu (excludeSelectors) est jugé. Le texte situé ailleurs dans la page est quand même mesuré, car le texte du périmètre peut se mettre à le chevaucher. Tant qu’une boîte de dialogue modale est ouverte, la page derrière elle est entièrement laissée de côté : le navigateur la rend inerte, et l’analyse juge la boîte de dialogue.
  • Marge (overflow-px) : parmi les textes qu’une boîte de découpage conserve en entier, la ligne qui a été la plus près d’être coupée. value indique de combien elle dépasse le bord de la boîte, en négatif tant qu’elle reste à l’intérieur, par rapport à 2px, au-delà desquels une ligne est en partie coupée (le premier constat) ; context.axis et context.text indiquent quel bord et quel texte. Elle est mesurée là où le texte grandit avec l’espacement supplémentaire, à la fin de ligne (à droite, ou à gauche dans un texte de droite à gauche) et en bas ; un bord de début ne compte qu’une fois qu’une ligne l’a dépassé. Un axe sur lequel la boîte a grandi avec l’espacement (un bloc de hauteur auto) suit son contenu et est laissé de côté, et un texte vertical n’a pas de marge. Le texte déplacé par une animation qui se répète (un bandeau défilant) est laissé de côté, puisque sa position dépend de l’instant où l’animation a été figée, tout comme une boîte qui coupe d’autres textes : c’est un constat. Seule une ligne à moins de 8px de la limite (à partir de 6px à l’intérieur du bord) compte comme proche : un texte plus enfoncé dans sa boîte ne donne donc aucune marge. measuredCount compte les paires texte–boîte de découpage comparées ; comme les constats, la marge couvre les 3 000 premiers nœuds texte.

Ce que rapporte un constat.

  • text : le début du texte, jusqu’à 60 caractères. Absent du constat d’une règle de feuille de style.
  • lines.shownBefore, lines.shownAfter (TEXT_CLIPPED_FURTHER) : le nombre de lignes du texte que sa boîte montrait en entier sans l’espacement et avec.
  • metrics.overflowPx (texte coupé) : de combien, en pixels CSS, la ligne a dépassé le bord de la boîte qui la découpe, avec l’espacement appliqué.
  • metrics.thresholdPx (texte coupé) : de combien elle peut dépasser avant d’échouer : une demi-em en largeur, ou la moitié de la hauteur de ligne en hauteur.
  • metrics.axis (texte coupé) : x lorsque la ligne a dépassé un côté, y le haut ou le bas.
  • container.widthPx, container.heightPx (texte coupé) : la taille de la boîte de découpe avec l’espacement appliqué.
  • viewport.width, viewport.height (texte coupé ou en chevauchement) : le viewport dans lequel la page a été mise en page, en pixels CSS. Un texte qui tient à une largeur peut être coupé à une autre.
  • other (texte en chevauchement) : le texte qu’il finit par chevaucher.
  • selector, property, value (une règle de feuille de style) : le sélecteur de la règle et la déclaration qui impose l’espacement.

Ces champs de data.details aident à lire et à reproduire un constat. À part reasonCode et les quelques champs que la page Schéma de sortie donne comme stables, ils ne constituent pas un contrat stable : un champ peut être renommé ou supprimé dans une version mineure, ne vous appuyez donc pas dessus.

Marge. Cette règle mesure overflow-px en pixels CSS, et la valeur doit rester sous le seuil. Quand une réussite est passée près du seuil, le champ margin du résultat désigne l’élément qui s’en est le plus approché tout en le respectant, si bien qu’un résultat qu’un petit changement ferait basculer se voit avant de basculer. Contrairement aux champs d’un constat, c’est un contrat stable. Voir Schéma de sortie.

Exemples

passDans un navigateur
<p>Opening hours today, and the rest of the week from nine to five.</p>

Le paragraphe n’a pas de taille fixe : le texte grandit avec l’espacement et rien n’est perdu.

failDans un navigateur
<style>
.hours { width: 19ch; height: 20px; overflow: hidden; }
</style>
<div class="hours">Opening hours today</div>

Avec une hauteur de ligne de 1,5, un espacement des lettres de 0,12em et des mots de 0,16em, le texte passe sur une deuxième ligne que la boîte coupe. Dans jsdom, qui n’a pas de mise en page, la règle lit seulement les feuilles de style et pose la question pour l’espacement imposé avec !important.

Comment vérifier

Quand cette règle ne peut pas trancher, elle renvoie cantTell et laisse la question à une personne. Chaque question qu’elle peut poser figure ici sous son code de raison, avec les étapes pour y répondre. Un constat porte les mêmes étapes dans howToCheck, dans la langue de l’analyse. Voir Schéma de sortie.

SPACING_NOT_APPLIED

  1. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important. Les règles ajoutées dans le panneau Styles ne sont pas bloquées par la politique de sécurité de la page.
  2. Faites défiler toute la page et cherchez du texte coupé, qui chevauche un autre texte ou qui disparaît.
  3. Là où du texte est coupé, vérifiez si la page propose un moyen de l’afficher en entier, comme un lien « Lire la suite » ou un bouton qui agrandit la zone. Cela ne compte que s’il est utilisable au clavier et qu’il affiche tout le texte avec l’espacement toujours appliqué.
  4. Vérifiez que les contrôles et les menus fonctionnent toujours et affichent tout leur texte.

Réussite. Tout le texte reste visible et lisible, ou le texte coupé peut être affiché en entier au clavier, et rien ne cesse de fonctionner avec l’espacement appliqué.

Échec. Avec l’espacement appliqué, du texte est coupé, se chevauche ou est perdu et ne peut pas être affiché en entier autrement, ce qui ne respecte pas le critère WCAG 1.4.12.

STYLESHEET_IMPORTANT

  1. Notez la règle, la propriété et la valeur indiquées par le rapport, et trouvez dans le panneau Éléments un élément auquel elle s’applique.
  2. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important.
  3. Vérifiez dans l’onglet Calculé si le line-height, le letter-spacing et le word-spacing de l’élément ont maintenant ces valeurs.
  4. Si ce n’est pas le cas, donnez à l’élément les mêmes valeurs dans son propre style (la section element.style en haut du panneau Styles), comme le ferait une feuille de style utilisateur, et vérifiez si son texte reste lisible.

Réussite. L’espacement de l’utilisateur s’applique toujours à l’élément, ou le contenu se lit bien sans lui.

Échec. La règle !important de la page empêche l’espacement de l’utilisateur de s’appliquer, ce qui ne respecte pas le critère WCAG 1.4.12.

TEXT_CLIPPED_FURTHER

  1. Repérez l’extrait de texte indiqué par le rapport et notez combien de lignes il affiche en entier.
  2. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important.
  3. Comptez les lignes qu’il affiche maintenant, et vérifiez si un lien « lire la suite » ou un autre moyen permet encore d’accéder au texte complet.

Réussite. L’extrait remplit toujours son rôle, et le texte complet est accessible d’une autre manière.

Échec. L’espacement coupe du contenu qui n’est accessible d’aucune autre manière, ce qui ne respecte pas le critère WCAG 1.4.12.

TEXT_CLIPPED_MOVING

  1. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important.
  2. Repérez le texte en mouvement indiqué par le rapport et observez-le pendant au moins un cycle complet de son animation.
  3. Mettez-le en pause s’il existe un contrôle pour cela, et vérifiez que tout son texte peut être lu à un moment donné.

Réussite. Chaque partie du texte en mouvement reste lisible pendant son cycle.

Échec. Une partie du texte n’apparaît jamais en entier une fois l’espacement appliqué, ce qui ne respecte pas le critère WCAG 1.4.12.

TEXT_CLIPPED_SCRIPT_SIZED

  1. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important.
  2. Repérez le texte indiqué par le rapport et attendez un instant : le script de la page peut redimensionner la zone qui l’entoure pour le texte plus long.
  3. S’il paraît toujours coupé, rendez la fenêtre du navigateur un peu plus étroite ou plus large, ou cliquez sur une zone vide de la page, ce qui amène de nombreuses pages à redimensionner leurs zones.
  4. Lisez le texte et vérifiez qu’il s’affiche en entier.

Réussite. Une fois que la page a réagi, la zone s’ajuste au texte et tout peut être lu avec l’espacement appliqué.

Échec. Le texte reste coupé avec l’espacement appliqué, même après avoir laissé à la page le temps de réagir, ce qui ne respecte pas le critère WCAG 1.4.12.

TEXT_CLIPPED_PARTLY

  1. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important.
  2. Repérez le texte indiqué par le rapport et regardez le bord de la boîte qui le coupe.
  3. Lisez le texte et vérifiez que chaque lettre reste reconnaissable, y compris le haut et le bas des lettres.
  4. Là où du texte est coupé, vérifiez si la page propose un moyen de l’afficher en entier, comme un lien « Lire la suite » ou un bouton qui agrandit la zone. Cela ne compte que s’il est utilisable au clavier et qu’il affiche tout le texte avec l’espacement toujours appliqué.

Réussite. Seule une fine bande au bord est coupée et tout le texte reste lisible, ou le texte entier peut être affiché autrement au clavier, avec l’espacement toujours appliqué.

Échec. Une partie du texte est coupée et ne peut plus être lue, et elle ne peut pas être affichée en entier autrement, ce qui ne respecte pas le critère WCAG 1.4.12 (F104).

TEXT_OVERLAPS

  1. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important.
  2. Repérez le texte indiqué par le rapport et le texte qu’il chevauche désormais.
  3. Lisez les deux et vérifiez si l’un d’eux devient difficile à lire là où ils se chevauchent.

Réussite. Le chevauchement se limite à une mince bande sur les bords et les deux textes restent lisibles.

Échec. Du texte est dessiné par-dessus un autre texte au point que l’un des deux devient illisible, ce qui ne respecte pas le critère WCAG 1.4.12 (F104).

VIEWPORT_SCROLL_LOCKED

  1. Fermez toute bannière, boîte de dialogue ou superposition ouverte sur la page, afin que la page puisse défiler.
  2. Dans le panneau Styles des outils de développement, ajoutez une nouvelle règle de style pour * définissant line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important, et une règle pour p définissant margin-bottom: 2em !important.
  3. Faites défiler jusqu’au texte indiqué par le rapport et vérifiez qu’il peut être atteint et lu.

Réussite. Une fois la superposition fermée, la page défile et tout le texte peut être atteint et lu.

Échec. Le texte reste hors d’atteinte une fois l’espacement appliqué, ce qui ne respecte pas le critère WCAG 1.4.12.

Voir le code source