Les resets CSS sont une collection de styles CSS qui défont le style par défaut du navigateur pour la plupart des éléments CSS.
Dernièrement j’ai vu des cas où des développeurs utilisaient display:contents
sur des listes et des titres pour supprimer leurs marges et leurs rembourrages (margin
et padding
), et d’une façon générale faire visuellement ce qu’un reset CSS pourrait faire. En résumé, ils utilisent display:contents
comme un reset CSS à deux sous.
C’est dangereux pour l’accessibilité.
Je vais vous expliquer pourquoi ci-dessous, parce que si j’ai dû faire des recherches pour m’en assurer, vous auriez plutôt intérêt à le lire.
- Qu’est-ce que
display:contents
? - Quelques implications pour l’accessibilité
- Des bugs dans la spec et dans les navigateurs
- Des tweets
- En résumé
Qu’est-ce que display:contents
?
Il vous serait utile de bien savoir de quoi nous sommes en train de parler. Vous pouvez aussi sauter cette partie si le sujet vous est déjà familier (c’est un peu long).
Vu par les développeurs
Dans sa forme la plus simple, display:contents
existe pour supprimer visuellement le conteneur de l’élément (la « box ») et le remplacer par son contenu. Sur le principe, il traite l’élément comme si les balises ouvrante et fermante avaient été supprimées et que le contenu était resté tout nu sur la page.
Ce qui peut être très utile quand on l’applique à une page pleine de soupe de <div>
s que vous voulez mettre en page avec les méthodes CSS grid ou flex. Ou peut-être que vous avez hérité d’une page en Bootstrap et de ses flots de <div>
s, et que vous voulez faire de l’amélioration progressive avec une grille CSS.
Ire Aderinokun fournit une bonne synthèse de la question dans How display : contents ; Works, bien que les navigateurs ne fassent pas exactement ce qu’elle annonce.
Hidde de Vries l’explique aussi dans son article More accessible markup with display : contents. Son article, cependant, n’approche pas display:contents
comme je l’ai vu se comporter.
D’après le W3C
La spécification CSS3 fournit aussi des indications :
L’élément lui-même ne génère pas de boîte, mais ses enfants et les pseudo-éléments génèrent toujours des boîtes et des flux textuels normaux. Pour pouvoir générer les boîtes et assurer la mise en page, l’élément doit être traité comme s’il avait été remplacé dans l’arbre des éléments par son contenu (y inclus ses enfants dans le code source et les pseudo-éléments, tels que
::before
et::after
, qui sont générés avant/après les enfants de l’élément comme des éléments normaux).Note : alors que seul l’arbre de la boîte est affecté, toute sémantique basée sur l’arbre du document, tels le filtrage par sélecteur, la gestion d’événements, et l’héritage de propriétés, n’est pas affectée.
Cette valeur se comporte comme
display:none
sur les éléments remplacés et autres éléments dont le rendu n’est pas entièrement contrôlé par CSS ; voir Appendice B : effets de display:contents sur des éléments inhabituels pour plus de détails.
[Note du traducteur : cette traduction n’est pas officielle, elle est faite uniquement pour les besoins de cet article et ne se substitue pas à une traduction française entérinée par le W3C le cas échéant.]
La liste des cas particuliers est peut-être encore plus intéressante :
<br>
<wbr>
<meter>
<progress>
<canvas>
<embed>
<object>
<audio>
<iframe>
<img>
<video>
<frame>
<frameset>
<input>
<textarea>
<select>
-
display: contents
se comporte comme display: none
.
<legend>
-
D’après HTML, une legend
avec un display: contents
n’est pas une légende rendue visuellement, elle n’a donc pas de capacité magique d’affichage. (Ainsi elle réagit à display: contents
de façon normale.)
<button>
<details>
<fieldset>
-
Ces éléments n’ont pas de comportement particulier; display: contents
supprime simplement leur conteneur principal, et leurs contenus sont rendus visuellement de façon normale.
- tout autre élément HTML
-
Se comporte normalement pour display: contents
.
Quelques implications pour l’accessibilité
De nos jours les navigateurs prennent chaque élément atteint par display:contents
et le font disparaître de l’arbre d’accessibilité. Si vous avez lu l’article où je parle de remettre de la sémantique de tableau dans les éléments <table> avec ARIA (une fois les propriétés CSS d’affichage appliquées), hé bien, ici, ça ne marche pas. Même pas un petit peu.
Une démo que vous pouvez refaire chez vous
J’ai inséré un CodePen ci-dessous, mais il est plus facile de tester la version de débug qui n’inclut pas l’environnement CodePen.
See the Pen Table with display:contents by Adrian Roselli (@aardrian) on CodePen.
Exemple avec un lecteur d’écran
Je l’ai parcouru avec NVDA et Firefox pour vous le montrer en action. J’essaie de naviguer par table (T), par liste (L), par bouton (B), et par titre de niveau 2 (2). Aucun n’est reconnu. Il peut être intéressant de noter que chacun de ces éléments comporte un rôle ARIA en doublon de son rôle natif.
Depuis que j’ai fait cette vidéo, j’ai modifié le CodePen pour inclure deux button
s, l’un avec un gestionnaire d’événement onkeypress
et tabindex="0"
pour montrer qu’il est mort pour un utilisateur au clavier. J’ai ajouté ce code parce que l’autre button
est encore cliquable et déclenche bien un événement onclick
.
L’arbre d’accessibilité
Pour vous détourner de l’idée que ce serait la faute des lecteurs d’écran, je peux vous assurer qu’aucune information de l’élément (y compris ARIA) n’atteint le lecteur d’écran. Ces saisies d’écran viennent de Chrome 66.
Des bugs dans la spec et dans les navigateurs
Dix jours avant mes tests, Hidde de Vries avait déjà ouvert des bugs pour les navigateurs sur la base de leur usage de display:contents
dans les mises en page en grilles :
- Firefox bug 1455357: Setting grid item to display:contents resets its accessible role
- Chromium Issue 835455: Element not exposed to accessibility tree when it is set to display: contents
- Safari bug 39630240 (que je ne peux pas voir parce que mon Apple ID n’a peut-être pas les bonnes permissions)
Après une discussion sur Twitter ce matin avec Ilya Streltsyn, il a pris l’initiative de faire remonter la question au groupe de travail CSS :
- CSSWG #2632: [css-display][css-aam][selectors-4]
How elements with
display:contents
get focused?
Des tweets
Je ne pense pas être le premier à remarquer display;contents
utilisé comme reset CSS, mais mes tweets de ce matin ont l’air d’avoir surpris un certain nombre de personnes, et j’en profite pour glaner de l’information sur ces problèmes.
[Note de traduction : j’ai laissé les messages en anglais comme vous le constaterez. Ils abondent dans le sens de l’auteur]
Oh wow – this discovery makes display: contents
useless for dealing with lists and other things. 😲
twitter.com/aardrian/statu… #a11y
This is bad behavior by browsers, but until it is fixed, the only acceptable use for display: contents
is to remove extra
divs that you added for your fallback layout but don't need for your grid layout.
Do
not use—yet—on semantic elements: <ul>, <nav>, <button>, <header>, etc twitter.com/aardrian/statu…
Interestingly enough, some other change to a web site *after* it was loaded will make the stuff reappear somehow, at least
in Firefox. @jcsteh investigated this just the week before last, and we have a bug in Bugzilla under investigation for this
problem. Whole Thread: 👇 twitter.com/aardrian/statu…
tl;dr: for me, _the_ use case for display:contents is increased accessibility, which now works nowhere, because of these
bugs.
It… It removes it from the CSS box tree too. It has all sorts of bad side effects if you try to use it like that.
Not only does using display: contents
as a element-reset hack create a major #a11y probem, it's also poorly supported.
Try all: initial
instead. It resets an element's
styles AND it's much better supported:
caniuse.com/#feat=css-all
caniuse.com/#feat=css-display-contents
twitter.com/aardrian/statu…
If the browsers implemented it as it was intended, it would be very useful, allowing you to have semantic markup wrappers
that are independent from your layout.
e.g. a <nav> list followed by
a search bar and a language selector, laid out as a single grid or flex container.
Indeed there are plenty of sensible reasons to have elements you might not want visually to create a box.
Yes, currently it is broken. Thank you for the excellent point about display:contents
elements getting focused! I opened
an issue in the CSSWG repo about it: github.com/w3c/csswg-draf…,
will file bugs for browsers as soon as the spec clarifies this!
En résumé
Pour l’instant veuillez n’utiliser display:contents
que si vous prévoyez de le tester avec les technologies d’assistance et que vous pouvez confirmer que le résultat fonctionne pour les utilisateurs.
Ceci est une traduction de Display : Contents Is Not a CSS Reset, par Adrian Roselli. Translated with permission.