Skip to content

Commit 4203e83

Browse files
committed
feat(post): masquage accessible de pointe
1 parent 61fe69f commit 4203e83

File tree

22 files changed

+775
-364
lines changed

22 files changed

+775
-364
lines changed

_src/posts/cache-cache-css/index.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
layout: "template/post.njk"
33
title: "Cache-cache CSS"
44
date: "2016-10-13T13:11:13"
5-
modified: "2021-03-05T17:07:37"
5+
modified: "2025-03-11"
66
permalink: "cache-cache-css/index.html"
77
excerpt: "Il existe une myriade de façon de masquer visuellement du texte en CSS tout en le maintenant accessible aux technologies d'assistance telles que les lecteurs d'écran. J'en agrège ici quelques-unes pour proposer une version que j'espère plus robuste."
88
tags: ["posts"]
@@ -14,6 +14,14 @@ Il existe de nombreuses façons de faire, que je ne détaillerai pas ici. Depuis
1414

1515
Mais elle n’est pas exempte de problème, désormais.
1616

17+
---
18+
19+
## Mise à jour
20+
21+
Depuis la dernière mise à jour en 2019, d’autres changements ont été apportés. Je les ai récapitulés dans [<cite>Masquage accessible de point</cite>](/masquage-accessible-de-pointe/).
22+
23+
---
24+
1725
## Propriété dépréciée
1826

1927
La «&nbsp;magie&nbsp;» de cette solution repose sur la propriété `clip`. Elle est simple à comprendre et très efficace. Seul bémol&nbsp;: `clip` est **déprécié par le module _[CSS masking](https://drafts.fxtf.org/css-masking-1/#clip-property)_** de niveau 1.
@@ -47,7 +55,6 @@ Et voilà, second problème résolu.
4755
Voilà la version finale que je propose actuellement&nbsp;:
4856

4957
```css
50-
5158
.sr-only {
5259
border: 0 !important;
5360
clip: rect(1px, 1px, 1px, 1px) !important;
@@ -105,7 +112,7 @@ Qu’en dites-vous&nbsp;?
105112

106113
### Les lecteurs d’écran sur mobile
107114

108-
19 octobre 2016
115+
<time datetime="2016-10-19">19 octobre 2016</time>
109116

110117
Ayant besoin de tests sur cette version pour vérifier qu’elle n’introduit pas de régressions, [Johan Ramon m’a remonté un bug étrange sur VoiceOver](https://twitter.com/johan_ramon/status/788372720224526336). En creusant un peu avec [Sylvain Pigeard](https://github.com/PigeardSylvain), il nous est apparu que `position: static` posait problème lors de la prise de focus d’un lien ayant la classe `.sr-only-focusable`.
111118

@@ -121,14 +128,22 @@ L’état des lieux est assez sombre&nbsp;: **les liens d’évitement ne marche
121128

122129
### Le référencement naturel
123130

124-
19 octobre 2016
131+
<time datetime="2016-10-19">19 octobre 2016</time>
125132

126133
[Steve Faulkner](https://twitter.com/stevefaulkner)&nbsp;du [Paciello Group](https://www.paciellogroup.com/blog/)&nbsp;— a posé la question au forum de support pour _webmasters_ de Google&nbsp;: [les contextes supplémentaires pour utilisateurs malvoyants ont-ils un effet négatif sur le positionnement dans les résultats de recherche&nbsp;?](https://productforums.google.com/forum/#!msg/webmasters/YJcZUhtMIE4/XkOEzVakBAAJ)
127134

128135
Réponse courte&nbsp;: **non** Cependant étant donné que ce texte n’apparaît pas de prime abord il est considéré comme du contenu secondaire et a donc un très faible impact sur le positionnement, et c’est une excellente chose puisque cela dissuade d’en abuser.
129136

130137
### Les débordements inopinés
131138

132-
18 janvier 2019
139+
<time datetime="2019-01-18">18 janvier 2019</time>
133140

134141
De multiples problèmes de débordements ont été observés, notamment sur Chrome, lorsque les éléments masqués sont contenus dans un élément avec `overflow: auto;`. [Le problème est résolu dans Boosted](https://github.com/Orange-OpenSource/Orange-Boosted-Bootstrap/issues/84) en ajoutant `margin: -1px;`.
142+
143+
---
144+
145+
## Mise à jour
146+
147+
Depuis la dernière mise à jour en 2019, d’autres changements ont été apportés. Je les ai récapitulés dans [<cite>Masquage accessible de point</cite>](/masquage-accessible-de-pointe/).
148+
149+
---
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
layout: "template/post.njk"
3+
title: "Masquage accessible de pointe"
4+
date: "2025-03-11"
5+
permalink: "masquage-accessible-de-pointe/index.html"
6+
excerpt: "Depuis ma dernière partie de [cache-cache CSS](https://wwww.ffoodd.fr/cache-cache-css/), les choses ont changé&nbsp;— quelques cas tordus sont apparus."
7+
description: "Depuis ma dernière partie de <a href='/cache-cache-css/'>cache-cache CSS</a>, les choses ont changé&nbsp;— quelques cas tordus sont apparus."
8+
metadescription: "Depuis ma dernière partie de cache-cache CSS, les choses ont changé — quelques cas tordus sont apparus."
9+
tags: ["posts"]
10+
commentsOpen: "true"
11+
---
12+
13+
La classe de masquage accessible `.visually-hidden`&nbsp;anciennement `.sr-only` dans Bootstrap&nbsp;— a beaucoup évolué au fil du temps. C’est pour ça que j’ai publié [<cite>cache-cache CSS</cite>](/cache-cache-css/) il y a quelques années, qui récapitulait l’état de l’art à ce moment.
14+
15+
Mais il n’y a pas que les techniques CSS qui évoluent… Les navigateurs, aussi. Et parfois, ça requièrs de l’adaptation&nbsp;!
16+
17+
## Un cas légendaire
18+
19+
Louis-Maxime Piton —&nbsp;un des mainteneurs de [Boosted (en anglais)](https://boosted.orange.com/) et inévitablement contributeur à [Bootstrap (en anglais)](https://getbootstrap.com)&nbsp;— a [proposé un correctif (sur GitHub, en anglais)](https://github.com/twbs/bootstrap/pull/37533) il y a plus de deux ans pour contourner [un problème provoqué par le masquage accessible appliqué à une légende de tableau (sur StackOverflow, en anglais)](https://stackoverflow.com/questions/31057955/why-are-table-borders-not-collapsing-when-caption-is-positioned/32063028#32063028).
20+
21+
Les `caption`, lorsqu’ils sont en position absolue, sont considérés comme des cellules de tableaux anonymes&nbsp;— et ça met la grouille dans la fusion des bordures, l’indispensable `border-collapse: collapse`.
22+
23+
Le correctif proposé est simplissime, bien qu’il puisse théoriquement poser des problèmes&nbsp;: n’appliquer la position absolue que si l’élément n’est pas un `caption`. C’est l’état actuel [du <em lang="en">mixin</em> dans Bootstrap (sur GitHub, en anglais)](https://github.com/twbs/bootstrap/blob/53171ad564b2d01bff7613d7210e93a5197a367b/scss/mixins/_visually-hidden.scss).
24+
25+
En résumé, voici la modification&nbsp;:
26+
27+
```css
28+
.visually-hidden:not(caption) {
29+
position: absolute !important;
30+
}
31+
```
32+
33+
## En cas de débordement
34+
35+
La semaine dernière, l’ami [Django Janny](https://www.djangojanny.net/) a relancé [le sujet sur Gist (en anglais) avec un cas marginal](https://gist.github.com/ffoodd/000b59f431e3e64e4ce1a24d5bb36034?permalink_comment_id=5468620#gistcomment-5468620)&nbsp;: un élément qui déborde, à l’intérieur d’un élément masqué visuellement.
36+
37+
En général, on ne masque qu’une portion de texte de cette façon&nbsp;: aucun élément bloc ne devrait s’y trouver&nbsp;— ni, en réalité, aucun enfant. La majorité du temps, le masquage accessible respecte implicitement les mêmes règles qu’un attribut `aria-label` par exemple&nbsp;: un texte simple et concis.
38+
39+
Mais c’est une règle implicite, et à ma connaissance aucune contre-indication n’a jamais été mentionnée quant à l’utilisation du masquage accessible sur une portion de DOM plus riche. Je l’ai par exemple fait lorsque j’ai amélioré les liens d’évitements sur [la documentation de Bootstrap (en anglais)](https://getbootstrap.com/docs/5.3/getting-started/introduction/), dont le conteneur est masqué visuellement —&nbsp;mais il apparaît à la prise de focus, nous faisant passer à côté du problème…
40+
41+
Depuis (au moins) 2019, les éléments en débordement deviennent focusables dans la plupart des navigateurs, pour palier un défaut d’accessibilité&nbsp;: ne pas pouvoir interagir avec un élément masqué par un débordement. [Cassey Lottman a retracé ce changement dans son article <cite lang="en">Elements with overflow: scroll become focusable</cite> (en anglais)](https://cassey.dev/til/2019-11-19-overflow-scroll-gets-focus/).
42+
43+
Ce qui, dans un élément masqué visuellement, devient un piège&nbsp;: on ne voit (évidemment) pas le focus.
44+
45+
La solution proposée par Django —&nbsp;et après quelques tests, la seule qui paraisse fonctionner&nbsp;— est d’[empêcher le débordement sur les enfants d’un élément masqué visuellement (sur CodePen, en anglais)](https://codepen.io/djangounet/pen/WbNpmMP?editors=1111)&nbsp;:
46+
47+
```css
48+
.visually-hidden * {
49+
overflow: hidden !important;
50+
}
51+
```
52+
53+
## La totale
54+
55+
Voici donc la version mise à jour de la technique de masquage accessible&nbsp;:
56+
57+
```css
58+
.visually-hidden {
59+
border: 0 !important;
60+
clip-path: inset(50%) !important;
61+
height: 1px !important;
62+
margin: -1px !important;
63+
overflow: hidden !important;
64+
padding: 0 !important;
65+
width: 1px !important;
66+
white-space: nowrap !important;
67+
}
68+
69+
.visually-hidden:not(caption) {
70+
position: absolute !important;
71+
}
72+
73+
.visually-hidden * {
74+
overflow: hidden !important;
75+
}
76+
```
77+
78+
J’en ai profité pour [proposer ce changement dans Bootstrap (sur GitHub, en anglais)](https://github.com/twbs/bootstrap/pull/41286)&nbsp;en citant Django bien entendu&nbsp;— et pour mettre à jour [le Gist servant souvent de référence (en anglais)](https://gist.github.com/ffoodd/000b59f431e3e64e4ce1a24d5bb36034).
79+
80+
Notez par ailleurs quelques autres changements succincts&nbsp;:
81+
82+
1. J’ai renommé `.sr-only` en `.visually-hidden` pour me conformer aux usages des <em lang="en">frameworks</em> populaires,
83+
2. Et nettoyé un peu le support de navigateurs anciens&nbsp;: plus de `clip` désormais, car [`clip-path` est très largement supporté](https://developer.mozilla.org/fr/docs/Web/CSS/clip-path).
84+
3. La variante pour démasquer le contenu lors de la prise de focus n’est plus une remise à zéro, mais une autre classe conditionnée à l’état&nbsp;: `.visually-hidden-focusable:not(:focus):not(:focus-within)`, à l’instar de ce qui est fait [dans Bootstrap depuis cinq ans déjà (sur GitHub, en anglais)](https://github.com/twbs/bootstrap/pull/32440).
85+
86+
87+

docs/cache-cache-css/index.html

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ <h2 class="h3-like description" itemprop="description">Il m&apos;arrive souvent
6262
<p>Et j’ai beau trouver ça idiot — masquer du texte pour certains utilisateurs et pas pour d’autres, ça me paraît incohérent avec l’accessibilité — c’est un besoin récurrent.</p>
6363
<p>Il existe de nombreuses façons de faire, que je ne détaillerai pas ici. Depuis quelques années, lorsque je le peux, j’utilise celle de <a href="https://twitter.com/thierrykoblentz">Thierry Koblentz</a> pour Yahoo! qui est décrite <a href="https://developer.yahoo.com/blogs/ydn/clip-hidden-content-better-accessibility-53456.html">sur le blog technique de Yahoo!</a> <a href="https://cssmojo.com/hide-content-from-sighted-users/">sur le blog de Thierry</a>. C’est de loin la plus complète, et la seule à ma connaissance à supporter la direction de texte de droite à gauche.</p>
6464
<p>Mais elle n’est pas exempte de problème, désormais.</p>
65+
<hr>
66+
<h2 id="mise-a-jour" tabindex="-1">Mise à jour</h2>
67+
<p>Depuis la dernière mise à jour en 2019, d’autres changements ont été apportés. Je les ai récapitulés dans <a href="/masquage-accessible-de-pointe/"><cite>Masquage accessible de point</cite></a>.</p>
68+
<hr>
6569
<h2 id="propriete-depreciee" tabindex="-1">Propriété dépréciée</h2>
6670
<p>La « magie » de cette solution repose sur la propriété <code>clip</code>. Elle est simple à comprendre et très efficace. Seul bémol : <code>clip</code> est <strong>déprécié par le module <em><a href="https://drafts.fxtf.org/css-masking-1/#clip-property">CSS masking</a></em></strong> de niveau 1.</p>
6771
<p>Pas de souci. La technique basée sur <code>clip</code> date un peu, il est normal qu’elle tombe en désuétude. La nouvelle spécification recommande l’utilisation de <code>clip-path</code> pour remplacer <code>clip</code>. Ce qui nous laisse pantois, puisque <a href="https://caniuse.com/#feat=css-clip-path">le support de <code>clip-path</code> est encore tout à fait relatif</a>. <strong>Nous devons conserver <code>clip</code> et ajouter <code>clip-path</code> en guise d’amélioration progressive</strong>.</p>
@@ -76,8 +80,7 @@ <h2 id="le-texte-ratatine" tabindex="-1">Le texte ratatiné</h2>
7680
<p>Et voilà, second problème résolu.</p>
7781
<h2 id="la-totale" tabindex="-1">La totale</h2>
7882
<p>Voilà la version finale que je propose actuellement :</p>
79-
<pre class="language-css" tabindex="0"><code class="language-css">
80-
<span class="token selector">.sr-only</span> <span class="token punctuation">{</span>
83+
<pre class="language-css" tabindex="0"><code class="language-css"><span class="token selector">.sr-only</span> <span class="token punctuation">{</span>
8184
<span class="token property">border</span><span class="token punctuation">:</span> 0 <span class="token important">!important</span><span class="token punctuation">;</span>
8285
<span class="token property">clip</span><span class="token punctuation">:</span> <span class="token function">rect</span><span class="token punctuation">(</span>1px<span class="token punctuation">,</span> 1px<span class="token punctuation">,</span> 1px<span class="token punctuation">,</span> 1px<span class="token punctuation">)</span> <span class="token important">!important</span><span class="token punctuation">;</span>
8386
<span class="token property">-webkit-clip-path</span><span class="token punctuation">:</span> <span class="token function">inset</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span> <span class="token important">!important</span><span class="token punctuation">;</span>
@@ -118,7 +121,7 @@ <h3 id="version-anglaise" tabindex="-1">Version anglaise</h3>
118121
<p><a href="https://twitter.com/KittyGiraudel">Kitty Giraudel</a> m’a fait l’honneur de <a href="https://kittygiraudel.com/2016/10/13/css-hide-and-seek/">traduire cet article en anglais et le publier sur son blog</a>. Merci !</p>
119122
<h2 id="modifications" tabindex="-1">Modifications</h2>
120123
<h3 id="les-lecteurs-d-ecran-sur-mobile" tabindex="-1">Les lecteurs d’écran sur mobile</h3>
121-
<p>19 octobre 2016</p>
124+
<p><time datetime="2016-10-19">19 octobre 2016</time></p>
122125
<p>Ayant besoin de tests sur cette version pour vérifier qu’elle n’introduit pas de régressions, <a href="https://twitter.com/johan_ramon/status/788372720224526336">Johan Ramon m’a remonté un bug étrange sur VoiceOver</a>. En creusant un peu avec <a href="https://github.com/PigeardSylvain">Sylvain Pigeard</a>, il nous est apparu que <code>position: static</code> posait problème lors de la prise de focus d’un lien ayant la classe <code>.sr-only-focusable</code>.</p>
123126
<p>Nous étions contents, lorsqu’en cherchant à avertir l’équipe de Bootstrap nous sommes tombés sur <a href="https://github.com/twbs/bootstrap/issues/20732">un ticket ouvert récemment qui implique également TalkBack</a>. <a href="https://twitter.com/patrick_h_lauke">Patrick H. Lauke</a>, en investiguant, a décelé de nombreuses incohérences dans la gestion du focus entre les diverses technologies d’assistance sur mobile. Il a ainsi ouvert des tickets un peu partout :</p>
124127
<ul>
@@ -130,19 +133,23 @@ <h3 id="les-lecteurs-d-ecran-sur-mobile" tabindex="-1">Les lecteurs d’écran s
130133
</ul>
131134
<p>L’état des lieux est assez sombre : <strong>les liens d’évitement ne marchent globalement pas sur les interfaces tactiles lorsqu’on utilise un lecteur d’écran</strong>. Ô joie.</p>
132135
<h3 id="le-referencement-naturel" tabindex="-1">Le référencement naturel</h3>
133-
<p>19 octobre 2016</p>
136+
<p><time datetime="2016-10-19">19 octobre 2016</time></p>
134137
<p><a href="https://twitter.com/stevefaulkner">Steve Faulkner</a> — du <a href="https://www.paciellogroup.com/blog/">Paciello Group</a> — a posé la question au forum de support pour <em>webmasters</em> de Google : <a href="https://productforums.google.com/forum/#!msg/webmasters/YJcZUhtMIE4/XkOEzVakBAAJ">les contextes supplémentaires pour utilisateurs malvoyants ont-ils un effet négatif sur le positionnement dans les résultats de recherche ?</a></p>
135138
<p>Réponse courte : <strong>non</strong> Cependant étant donné que ce texte n’apparaît pas de prime abord il est considéré comme du contenu secondaire et a donc un très faible impact sur le positionnement, et c’est une excellente chose puisque cela dissuade d’en abuser.</p>
136139
<h3 id="les-debordements-inopines" tabindex="-1">Les débordements inopinés</h3>
137-
<p>18 janvier 2019</p>
140+
<p><time datetime="2019-01-18">18 janvier 2019</time></p>
138141
<p>De multiples problèmes de débordements ont été observés, notamment sur Chrome, lorsque les éléments masqués sont contenus dans un élément avec <code>overflow: auto;</code>. <a href="https://github.com/Orange-OpenSource/Orange-Boosted-Bootstrap/issues/84">Le problème est résolu dans Boosted</a> en ajoutant <code>margin: -1px;</code>.</p>
142+
<hr>
143+
<h2 id="mise-a-jour-1" tabindex="-1">Mise à jour</h2>
144+
<p>Depuis la dernière mise à jour en 2019, d’autres changements ont été apportés. Je les ai récapitulés dans <a href="/masquage-accessible-de-pointe/"><cite>Masquage accessible de point</cite></a>.</p>
145+
<hr>
139146

140147
</div>
141148
<footer class="small mt2">
142149
<p class="pl2 mt0 pt1">
143150
Article rédigé par <strong itemprop="author"><span class="fn">Gaël Poupard</span></strong>.
144151
Publié le <time class="updated" datetime="2016-10-13T13:11:13" itemprop="datePublished">13 octobre 2016</time>
145-
et modifié le <time class="updated" datetime="2021-03-05T17:07:37" itemprop="dateModified">5 mars 2021</time>.
152+
et modifié le <time class="updated" datetime="2025-03-11" itemprop="dateModified">11 mars 2025</time>.
146153
</p>
147154
</footer>
148155
</article>
@@ -329,7 +336,7 @@ <h3 id="les-debordements-inopines" tabindex="-1">Les débordements inopinés</h3
329336
<div class="aside pt1 pr3 pb1 pl2">
330337
<h3 class="tk-bello-pro h2-like m-reset">Sommaire</h3>
331338
<div class="textwidget">
332-
<ol><li><a href="#propriete-depreciee">Propriété dépréciée</a></li><li><a href="#le-texte-ratatine">Le texte ratatiné</a></li><li><a href="#la-totale">La totale</a></li><li><a href="#code-et-traduction">Code et traduction</a></li><li><a href="#modifications">Modifications</a></li><li><a href="#comments">Commentaires</a></li></ol>
339+
<ol><li><a href="#mise-a-jour">Mise à jour</a></li><li><a href="#propriete-depreciee">Propriété dépréciée</a></li><li><a href="#le-texte-ratatine">Le texte ratatiné</a></li><li><a href="#la-totale">La totale</a></li><li><a href="#code-et-traduction">Code et traduction</a></li><li><a href="#modifications">Modifications</a></li><li><a href="#mise-a-jour-1">Mise à jour</a></li><li><a href="#comments">Commentaires</a></li></ol>
333340
</div>
334341
</div>
335342
</aside>

0 commit comments

Comments
 (0)