It’s Mid-2022 and Browsers (Mostly Safari) Still Break Accessibility via Display Properties
It was late 2020 when I last tested how browsers use CSS display
properties to break the semantics of elements.
I had been waiting for Safari to fix how it handles display: contents
for four years now, and was excited when the announcement came in June. Then I started testing the latest Safari Technical Preview and the results were not good. That prompted me to give each of Chrome, Firefox, and Safari a fresh run to see how they performed.
The following results are each set in a table with a numbered list following that provides more detail on any cells that are numbered:
CSS | <tr> , <th> , <td> |
<ul> , <ol> , <dl> |
<h#> |
<button> |
---|---|---|---|---|
display: flex |
✔ | ✔ | ✔ | ✔ |
display: grid |
✔ | ✔ | ✔ | ✔ |
display: block |
✔ | ✔ | ✔ | ✔ |
display: inline-block |
✔ | ✔ | ✔ | ✔ |
display: contents |
✔1 | ❌2,3 | ✔4 | ❌5,6 |
- There was a Chrome 113 regression where cell semantics (which have
display: contents
were removed from the accessibility tree. This was fixed in Chrome 115. 1448706 <ol>
s and<ul>
s are not treated as lists, but<dl>
s perform fine.- There was a Chrome 113 regression where description lists had no list item semantics. This was fixed in Chrome 115. 1448706
- There was a Chrome 113 regression where headings no longer conveyed semantics. This was fixed in Chrome 115. 1448706
- Shows as a button in the accessibility inspector, but does not receive keyboard focus; cannot be navigated with JAWS 2022 button command (B); can be activated with a mouse, touch, and screen reader virtual cursor. 1366037
- As of Chrome 115, still does not receive keyboard focus (so inoperable with keyboard) but now can be activated with screen reader commands.
CSS | <tr> , <th> , <td> |
<ul> , <ol> , <dl> |
<h#> |
<button> |
---|---|---|---|---|
display: flex |
❌1,2 ✔3 | ✔ | ✔ | ✔ |
display: grid |
❌1,2 ✔3 | ✔ | ✔ | ✔ |
display: block |
✔ | ✔ | ✔ | ✔ |
display: inline-block |
✔ | ✔4 | ✔ | ✔ |
display: contents |
✔ | ✔4 | ✔ | ❌5 |
<th>
s withflex
andgrid
are exposed as cells, not headers. 1711273- Using NVDA 2022.1–2023.1, the table reports the wrong number of rows and columns and cannot be navigated with table navigation commands (Ctrl + Alt + ←↑→↓).
- Tested in Firefox 113 and all is well.
- Inserts text leaf between each list item; NVDA announces each item in the list when navigating by list (L).
- Shows as a button in the accessibility inspector, but does not receive keyboard focus; cannot be navigated with NVDA button command (B); can be activated with a mouse, touch, and screen reader virtual cursor; dev tools show a keyboard use warning. 1791648
CSS | <tr> , <th> , <td> |
<ul> , <ol> , <dl> |
<h#> |
<button> |
---|---|---|---|---|
display: flex |
❌1 ✔11 | ✔ | ✔ | ✔ |
display: grid |
❌1 ✔11 | ✔ | ✔ | ✔ |
display: block |
❌1 ✔11 | ❌3 | ✔ | ✔ |
display: inline-block |
❌1 ✔11 | ❌3 | ✔ | ✔ |
display: contents |
❌2 ✔11 | ❌3,4,10 | ✔ | ❌5,6,7,8,9 |
- VoiceOver announces the wrong column and row count for each table; VoiceOver does not announce column headers when moving between columns; VoiceOver table navigation commands do not work (Ctrl + Option + ⌘ + ←↑→↓). 239478, 239479
- VoiceOver announces the entirety of each row as a run-on and announces no column nor cell counts. This appears to be a regression in Safari 16.5.
- VoiceOver does not announce ordered or unordered lists as lists (description lists are fine); VoiceOver does not navigate to ordered or unordered lists with list navigation (Ctrl + Option + ⌘ + X). 243486, 243373, 259487
- VoiceOver announces the entirety of each description list as a run-on. This appears to be a regression in Safari 16.5.
- Does not receive keyboard focus; cannot be navigated with VoiceOver button command (Ctrl + Option + ⌘ + J); can be activated with a mouse. 243486, 255149
- As of Safari TP 151, can be navigated with VoiceOver button command (Ctrl + Option + ⌘ + J) but its accessible name is not announced.
- As of Safari TP 152, its accessible name is announced.
- Safari 16 has regressed from Safari TP 152; the accessible name is not announced and it has none in the accessibility tree.
- In Safari 16.5 it announces as button, can be navigated as a button with VoiceOver only. It can be activated with VoiceOver Ctrl + Option + Space only. It does not accept keyboard focus and so cannot be activated with keyboard alone.
- Safari 17 now treats description lists as description lists (no run-on announcement).
- Works as expected as of Safari 17.
CSS | <tr> , <th> , <td> |
<ul> , <ol> , <dl> |
<h#> |
<button> |
---|---|---|---|---|
display: flex |
✔ | ✔ | ✔ | ✔ |
display: grid |
✔ | ✔ | ✔ | ✔ |
display: block |
✔ | ✔ | ✔ | ✔ |
display: inline-block |
✔ | ✔ | ✔ | ✔ |
display: contents |
✔1 | ❌2,3 | ✔4 | ❌5,6 |
- There was a Chrome 113 regression where cell semantics (which have
display: contents
were removed from the accessibility tree. This was fixed in Chrome 115. 1448706 <ol>
s and<ul>
s are not treated as lists, but<dl>
s perform fine.- There was a Chrome 113 regression where description lists had no list item semantics. This was fixed in Chrome 115. 1448706
- There was a Chrome 113 regression where headings no longer conveyed semantics. This was fixed in Chrome 115. 1448706
- Does not announce as a button and is not exposed when navigating by controls, but can be activated. Also has no focus style.
- As of Chrome 115, still does not receive keyboard focus (so inoperable with keyboard) but now can be activated with screen reader commands.
CSS | <tr> , <th> , <td> |
<ul> , <ol> , <dl> |
<h#> |
<button> |
---|---|---|---|---|
display: flex |
❌1 ✔6 | ✔ | ✔ | ✔ |
display: grid |
❌1 ✔6 | ✔ | ✔ | ✔ |
display: block |
❌2 ✔6 | ❌3 | ✔ | ✔ |
display: inline-block |
❌2 ✔6 | ❌3 | ✔ | ✔ |
display: contents |
❌1,2 ✔6 | ❌3 | ❌7 | ❌4 ✔5 |
- Table data cannot be accessed using VoiceOver when swiping or using read-all, and swiping from within table after using explore-by-touch does not advance to next cell. This appears to be a regression in Safari 16.5 (previously you could at least move through the text). 257458
- VoiceOver treats all cells as in column 1 and does not provide column headers. 243474
- VoiceOver does not announce ordered or unordered lists as lists (description lists are fine).
- Fires on double-tap with VoiceOver.
- In Safari 16.5 it announces as button, can be navigated as a button, and activates with and without VoiceOver. It still has no default focus ring.
- Works as expected as of Safari 17.
- Announces as heading as of Safari 17, but can not be navigated as a heading. 261978
Verdict
Chrome cleaned itself up and has held steady for more than 20 versions. Firefox needs work, but at least saw a tiny improvement. Safari made one tiny improvement but has a much bigger deficit, and I don’t trust it will improve much given its now twice-promised fix for display: contents
.
Tests
The following four embedded CodePens are what I used for testing. These do not account for all scenarios or use cases, but at least provide a baseline set of results. They were all created in early 2020. I adapted them by adding horizontal rules between each test since VoiceOver was concatenating some elements with display: contents
to the prior element.
Each links to a CodePen debug mode so you can test it directly, without the iframe or wrapper cruft.
HTML Tables
Visit the tables test in debug mode.
See the Pen Tables with Assorted Display Properties by Adrian Roselli (@aardrian) on CodePen.
Lists
Visit the lists test in debug mode.
See the Pen Lists with Assorted Display Properties by Adrian Roselli (@aardrian) on CodePen.
Headings
Visit the headings test in debug mode.
See the Pen Headings with Assorted Display Properties by Adrian Roselli (@aardrian) on CodePen.
Buttons
Visit the buttons test in debug mode.
See the Pen Buttons with Assorted Display Properties by Adrian Roselli (@aardrian) on CodePen.
References
I have not gone through all the old browser bugs, identified outstanding open bugs, nor filed fresh bugs. I just don’t have the energy. I am hoping readers can confirm or deny my findings, however, so if/when I muster that energy I have confirmation these issues aren’t just a failing on my end.
I have written about display properties, tables, and accessibility a bunch over the last few years. Others have also kicked in a pile of posts. This list is not exhaustive.
- On this site:
- It’s OK to Use Tables, 16 July 2012
- Hey, It’s Still OK to Use Tables, 1 November 2017
- A Responsive Accessible Table, 2 November 2017
- Tables, CSS Display Properties, and ARIA, 20 February 2018
- Tables, JSON, CSS, ARIA, RWD, TLAs…, 2 April 2018
- Display: Contents Is Not a CSS Reset, 1 May 2018
- Functions to Add ARIA to Tables and Lists, 12 May 2018
- a11yTO Conf: CSS Display Properties versus HTML Semantics, 21 October 2020
- CSS3 — Appendix B: Effects of display: contents on Unusual Elements
- Data Tables by Heydon Pickering
- Short note on what CSS display properties do to table semantics by Steve Faulkner, 4 March 2018
- How display: contents; Works by Ire Aderinokun, 27 Mar 2018
- More accessible markup with display: contents by Hidde de Vries, 20 April 2018, updated to reference this post
Update: 15 July 2022
I heard back from someone who works on WebKit (finally) and he confirmed the issues I found with the following bugs:
- Bug 242779 – AX: display:contents elements are inserted in the wrong position when they have inline renderer siblings, 14 July 2022
- Bug 239479 – AX: Support display:contents for table elements, 18 April 2022
Update: 22 July 2022
I tested Safari Technology Preview 149 today. No change.
Update: 4 August 2022
I tested Safari Technology Preview 150 today on macOS 12.5. No change.
Update: 6 August 2022
More updates from Tyler Wilcock, namely that three commits have landed in WebKit that address the heading and button examples in this post:
- AX: An unnecessary group is created for every block-flow box with no other useful AX semantics
- Closes new bug Bug 243373 – AX: An unnecessary group is created for every block-flow box with no other useful AX semantics, 30 July 2022
- Also closes its older duplicate Bug 242779 – AX: display:contents elements are inserted in the wrong position when they have inline renderer siblings, 14 July 2022
- AX: On iOS, display:contents elements are inserted in the wrong position when they have inline renderer siblings
- AX: AXCoreObject
::textUnderElement always returns an empty string for display:contents elements - Closes new bug Bug 243486 – AX: AXCoreObject::textUnderElement always returns an empty string for display:contents elements, 3 August 2022
I am thrilled to see the now-rapid progress from Tyler specifically. Compared to the current silence from Apple’s dedicated developer relations arm, past Apple mis-representation of fixes, and years of Apple’s failure to test for these obvious issues, this has been a breath of fresh air.
No idea which Safari Technical Preview will see these updates, but I am hopeful they will make it to Safari 16.
Update: 16 August 2022
I tested Safari Technology Preview 151 today on macOS 12.5.1. No change except a button with display: contents
is now partially exposed in one context.
Update: 27 August 2022
I tested Safari Technology Preview 152 today. No change except a button with display: contents
now has its accessible name announced.
Update: 11 September 2022
I tested Safari Technology Preview 153 today. No changes.
Update: 12 September 2022
I tested Safari 16 on macOS 12.6 today. It is equivalent to Safari TP 151. Tables with display properties are difficult to impossible to navigate with VoiceOver. Buttons with display: contents
have no accessible name and do not activate on Enter . The minor improvements since Safari 15 (and before) are not enough to make buttons or tables accessibility supported on macOS. All this despite the following claim today:
Safari 16 introduces a re-architecture of WebKit’s accessibility support on macOS. […] Safari 16 also greatly improves accessibility support for elements with
display:contents
by ensuring they are properly represented in the accessibility tree.
And this claim in June 2022:
I’m so happy that the severe mistake implementing `display: contents` and how it impacts the accessibility tree — one that originally shipped in all browsers — is now finally fixed in all browsers.
(Including on iOS! Ooops my bug on Can I Use.) pic.twitter.com/IGrvMTM1Rv
And this claim in March 2022:
WebKit fixed an accessibility bug with
display:contents
, which incorrectly hid content from the accessibility tree. This fix makes it possible to freely use this display value to remove a box from the DOM tree, while still including its children. This can be useful when you want to adjust which box is the child of a Flexbox or Grid container, for instance.
I really wish Apple had a dedicated Safari Twitter account instead of hanging its evangelist and/or the open source WebKit project out there to take the heat. That is unfair.
Remember that this is not an excuse to beat up the devs at Apple. If you are doing that, you are being unnecessarily mean to individuals who may have no control over broader organizational decisions. Do not be that guy / person / jerk.
Update: 13 September 2022
I filed an issue to update the Can I Use entry for display: block
, and it was merged overnight: #6451: Safari 16 (release version) still broken
The Can I Use flex
and grid
data comes from the MDN browser-compat-data, so I filed an issue there: #17776 css.properties.display – Safari (thru 16) flex, grid, contents problems
Update: 17 September 2022
Apple’s devrel team came through and filed another PR at Can I Use (while still engaging me in my PR) and undid my changes. The good news is that for the first time Can I Use reflects that Safari 15.x and older never properly supported display: contents
, acknowldegment of its prior false claims. The less good news is that both Apple and Can I Use believe that Safari supports display: contents
when using it on buttons or tables renders them inaccessible in Safari 16. Clearly we have different ideas of the term supported.
Update: 20 September 2022
Following some informal community polling, Can I Use has restored Safari’s “partial support” entry for display: contents
:
My efforts have probably earned me no fans at Apple, though at least one Apple devrel person might agree with the change.
Update: 13 November 2022
No improvements in Safari 16.1. Here I demonstrate how the row and column counts are way off for the tables.
Here I am using Chrome 107, Firefox 106, and Safari 16.1 trying to Tab<button>
with display: contents
. It is worth noting that neither adding role="button"
nor tabindex="0"
will fix this.
Update: 29 November 2022
Promising work on resolving a Firefox bug where <th>
s with CSS flex
and grid
are exposed as cells, not headers:
This revision fixes the problem by moving the th NativeRole logic into the TableCellAccessible class, then calling that logic from both the ARIA grid cell accessible NativeRole and from HTMLTableHeaderCellAccessible, as before. This revision also updates tests reliant on the old behavior, including beefing up an existing test aimed at this bug specifically.
When that deploys it will leave Safari ≤16.1 as the last browser that breaks tables using CSS display properties.
Update: 20 December 2022
Stumbled across this piece of advice on Twitter promoting the use of display: contents
:
The HTML
<details>
element1 cannot become a flexbox or grid container (display: flex
anddisplay: grid
are ignored). This restriction is specified in the HTML Standard (The2) and implemented in all browsers. It is possible to work around this limitation with<details>
element is expected to render as a block boxdisplay: contents
3. […]
- developer.mozilla.org/docs/Web
/HTML/Element /details - html.spec.whatwg.org/multipage
/rendering.html #the-details-and-summary-elements - mastodon.social/@simevidas
/109538578812286095 […]
This is a case of trying to solve one very specific problem, layout core to an element, with a flamethrower and no regard for what else goes up in flames. In this case it is keyboard accessibility. To demonstrate that, I made a demo:
See the Pen Untitled by Adrian Roselli (@aardrian) on CodePen.
This is the outcome of specs that do not clarify how the content model should (or should not) be affected, browsers that ignore the bug for years, and developers who cannot be bothered to test with the one device attached to all their computers (keyboard, for those reading who never use on for testing).
The CSS display: contents
property looks like such a simple salve, but in the end guarantees an access barrier.
Update: 8 April 2023
I tested Safari 16.4 on macOS 12.6.4 today. No changes.
Meanwhile, Chromium has a change ready to go that will allow elements with display:contents
to be focused (3910374), which is meant to honor CSSWG issue #2632 stating Elements that have
.
display: contents
can still be focused…
David Baron also filed a WebKit bug and requests for Mozilla and WebKit to take a position on display: contents
focusability specifically:
- WebKit Bug 255149 – elements with CSS display:contents are not focusable
- #772 Request for Mozilla Position: focusability of elements with display:contents
- WebKit #164 focusability of elements with CSS display:contents
Update: 24 May 2023
Safari on iPadOS 16.5 seems to have regressed since I can no longer get to table contents using read-all or swiping when the table has flex
, grid
, or block
. I am forced to use explore by touch to get into the table, and even then I cannot move between cells with swiping. On the bright side, buttons work well now with contents
(though I would like a default focus outline).
Safari 16.5 on macOS also appears to have regressed with tables and description lists that have display: contents
. Buttons, while improved, are sadly still inaccessible to keyboard users when using contents
.
Firefox 113 on Windows fixed a long-standing bug with tables, so congratulations are due there.
Chrome 113 on Windows and Android seems to have decided anything with display: contents
must have its semantics stripped. This change may have happened prior to Chrome 113, which is my fault for not testing each release. Either way, tables, lists, and headings are now broken and buttons remain broken.
In response to my social media posts about this today, David Baron promptly filed a Chromium issue: 1448706: elements with display:contents no longer exposed in accessibility tree
Update: 30 May 2023
Within 48 hours of me posting the Chrome regression on Mastodon, folks from the Chrome team (current and past) confirmed the regression, identified the cause, filed an issue, fixed the issue, and queued it to roll out in Chrome 115 (scheduled for 12 July). Thanks to David Baron, Alice Boxhall, and Aaron Leventhal.
While this kind of pro-active bug fix is great to see in action, there is still a significant barrier for users that will take about 3 months and 2+ versions for them to see fixed.
Meanwhile, I filed a new bug against Safari on iPadOS 16.5, Bug 257458 – AX: Tables with display properties are skipped, report wrong col/row counts, which includes the following video:
In the Safari issue I cite eighteen distinct bugs:
- Tables with
display: flex
on the<tr>
cannot be navigated into using swipe gestures (swipe right or left). - Tables with
display: flex
on the<tr>
are skipped when using read-all. - Tables with
display: grid
on the<tr>
cannot be navigated into using swipe gestures (swipe right or left) - Tables with
display: grid
on the<tr>
are skipped when using read-all. - Tables with
display: block
on the<td>
and<th>
give the wrong column count. - Tables with
display: block
on the<td>
and<th>
announce each<th>
with the first<th>
when first entering a row. - Tables with
display: block
on the<td>
and<th>
announce each column header<th>
as a row header. - Tables with
display: block
on the<td>
and<th>
announce each column header<th>
as column 1. - Tables with
display: block
on the<td>
and<th>
announce each<td>
with the wrong or no column header. - Tables with
display: block
on the<td>
and<th>
announce each<td>
as column 1. - Tables with
display: inline-block
on the<td>
and<th>
give the wrong column count. - Tables with
display: inline-block
on the<td>
and<th>
announce each<th>
with the first<th>
when first entering a row. - Tables with
display: inline-block
on the<td>
and<th>
announce each column header<th>
as a row header. - Tables with
display: inline-block
on the<td>
and<th>
announce each column header<th>
as column 1. - Tables with
display: inline-block
on the<td>
and<th>
announce each<td>
with no column header. - Tables with
display: inline-block
on the<td>
and<th>
announce each<td>
as column 1. - Tables with
display: contents
on the<td>
cannot be navigated into using swipe gestures (swipe right or left). - Tables with
display: contents
on the<td>
are skipped when using read-all.
I filed the following additional issues/PRs:
- MDN Browser Compat: #19994: Safari Table Support – CSS Display Properties Break Tables
- Pull request for CSS
grid
at Can I Use: #6729: Update css-grid.json for Safari bugs - Pull request for CSS
flex
at Can I Use: #6730: Update flexbox.json for Safari bugs - Pull request for CSS inline-block at Can I Use (there appears to be no entry for
block
, but the same bugs apply): #6731: Update inline-block.json for Safari bugs
I have low hopes for the MDN Brower Compat charts updating since #17776: css.properties.display – Safari (thru 16) flex, grid, contents problems has been open and untouched since September 2022.
Similarly, Safari issue Bug 239479: AX: Support display:contents for table elements has sat for over a year (filed 18 April 2022).
Update: 7 June 2023
I updated Bug 257458 – AX: Tables with display properties are skipped, report wrong col/row counts to include results of testing with Safari 16.5 and VoiceOver on macOS 12.6.6:
- Tables with
display: flex
on the<tr>
cannot be navigated into using table navigation. - Tables with
display: flex
on the<tr>
are skipped when using read-all. - Tables with
display: flex
on the<tr>
cannot be navigated into using swipe gestures. - Tables with
display: flex
on the<tr>
are skipped when using read-all. - Tables with
display: block
on the<td>
and<th>
give the wrong column count. - Tables with
display: block
on the<th>
announce each as a cell. - Tables with
display: block
on the<td>
and<th>
do not support navigating within a column. - Tables with
display: block
on the<td>
and<th>
do not announce column headers. - Tables with
display: inline-block
on the<td>
and<th>
give the wrong column count. - Tables with
display: inline-block
on the<td>
and<th>
announce the entirety of cells in a row as a single node. - Tables with
display: inline-block
on the<td>
and<th>
do not support navigating within a column (because it is treated as one column). - Tables with
display: inline-block
on the<td>
and<th>
do not announce column headers. - Tables with
display: contents
on the<td>
and<th>
cannot be navigated into using table navigation. - Tables with
display: contents
on the<td>
and<th>
are skipped when using read-all. - Tables with
display: contents
on the<td>
and<th>
have each row read as a single string of text.
So far I have seen no signals about this from Apple’s WWDC Safari and CSS talk, despite demonstrating some of these properties.
The Safari 17 beta announcement suggests some fixes for display: contents
, but not for the issues I cite here. Which is insight that there are likely far more issues than the four types of elements I have tracked in this post.
Update: 21 July 2023
Progress in Safari Technology Preview 174 on macOS. Items 19–33 are addressed. I found two new issues, which are a function of the fixes:
- Tables with
display: contents
on the<td>
and<th>
can be navigated into using table navigation, but VoiceOver announces each cell as “blank”. - Tables with
display: contents
on the<td>
and<th>
do not announce cell contents when using read-all. VoiceOver simply announces the column and row position.
I added these to the Safari bug that has gottent traction. I am not updating the support table owing to regressions I have seen in other TPs. I will update it when and if the fixes come to Safari 17.
I did not test Safari TP on iPadOS as I cannot seem to locate a TP for the platform.
Update: 13 August 2023
More progress in Safari Technology Preview 176 on macOS. The two new bugs I found are fixed. Granted, they should never had made it to the TP where I could find them, but at least I someone (me) caught them.
I did not test on iPadOS nor iPhoneOS. I did not re-test any prior issues for regressions. Apple is not paying me enough (nothing, actually) to do all of its QA.
I am not updating the support table above owing to regressions I have seen in other TPs. I will update it when and if the fixes come to Safari 17. Safari 17 is in beta now, but I am not testing it. I also understand not all Safari 17 features will be supported in macOS 12 or even 13, but I see no reason these fixes would not be. It would be a shame if users would have to upgrade hardware just to use tables for the first time in years.
Update: 14 August 2023
I confirmed that Chrome 115 fixes the regresions I identifed in May. Lists and buttons with display: contents
are still broken. This is most obvious with TalkBack where navigating to the sample lists rattles off the entire list as one single string of text.
Update: 22 September 2023
Significant progress in Safari 17 for iPadOS. Tables work now, which is spectacular. I find it odd that calling a native HTML element that only functions correctly in assistive technology years after the issue was reported “spectacular” when it should simply be expected, but here we are.
I did not expect lists to get any update. Apple has made a decision on that which is unlikely to change. It annoys some users, not others, and makes devs grumpy.
Headings with display: contents
now announce as headings when you encounter them, but you cannot navigate by them. That is a disappointment because it feels like Safari was so close and Safari Technology Preview 179 on macOS does not have this problem. Which makes this statement not quite accurate:
WebKit for Safari 17.0 fixes our remaining accessibility issues with
display:contents
.
Buttons continue to not have a focus ring, but all browsers are struggling with this.
Update: 7 October 2023
Very good progress in Safari 17. Tables and description lists are no longer broken when display
properties are applied. Buttons with display: contents
, however, are still inoperable by keyboard users and problematic for VO users (and I confirmed is also the case in Safari TP 180).
Meanwhile, the heading issue I reported for Safari 17 on iPadOS (261978 – AX: Headings with `display: contents` cannot be navigated) has been marked as a VoiceOver issue with no insight when it will be fixed. But marking it a VoiceOver issue means Safari can claim to have no bug so yay?
Apple seems reasonably confident it has finally fixed its historically years-lagging support (despite prior claims), and so has been doing the rounds suddenly arguing all the other browsers and specs need to fix display: contents
issues while using its own claims of (abruptly and questionably) better support to bolster them:
- CSS Working Group Comment on #3040 [css-a11y][css-display] display: contents; strips semantic role from elements from 2018.
- Web Platform Tests #568
display: contents
I also filed a PR with Can I Use to amend the one filed by Apple three weeks ago (I was unable to review owing to travel and this is not my job slash no one is paying me).
With Safari almost there on basic support and Apple now pushing for the specs and browsers to agree, after sitting it out for a few years, I am excited that the end is in sight. Which I expect before WCAG 3.
Update: 11 June 2024
Filed a new bug on Safari and how it handles a display property with tables: 275366 – AX: Tables with show/hide rows report wrong counts and block access to some rows in VoiceOver.
While this falls down over display: none
versus flex
or grid
or contents
, its still a display
property that had been well supported when I first made the example.
After all, who doesn’t like regression testing years-old features with every Safari release?
Update: 5 September 2024
Ahmad Shadeed discusses display: contents
in a new post and specifically notes accessibility concerns:
CSS
display: contents
is known to cause accessbility issues when used with HTML tables, headings, buttons, and lists. Please make sure to avoid using it on such elements. Here are some further resources:
Those four things he cites are simply what I tested. It required too much effort on my part to test everything, so I used a sub-set of HTML elements that covered a good range of features.
More direct advice would be: do not use display: contents
on anything that can take focus or is interactive. Probably avoid it on things with richer semantics (such as tables and lists and headings and so on).
Also, be cautious with reading order. Pay attention to the section of this CSS Day talk related to display: contents
, at roughly 36:30.
YouTube: Layout and Reading Order | Rachel Andrew | CSS Day 2024, 50:46
Then go read Request for developer feedback on reading-flow and elements with display: contents. If you work in accessibility in particular, please weigh in. Part of the reason display: contents
is such a mess is because it was poorly specified and the needed digital accessibility expertise was not part of that process.
Update: 16 September 2024
I have cautioned for some time now, including the prior update, that you must test every use of display: contents
and not rely solely on my limited tested in this post (and prior posts) nor claims of browsers.
As evidence:
Fixed
display: contents
ontbody
elements preventing table rows from being properly exposed in the accessibility tree. (282413@main) (129131780)
In other words, tables are still broken in Safari if you use display: contents
, and will be at least until this latest fix makes it to a production Safari release. I have no interest in going through every permutation of every table construct to test other things Apple has missed. That’s Apple’s job.
Update: 21 November 2024
Confirmation of the message in the update just above:
i am horrified to report that safari continues to have #accessibility issues with display:contents.
this time, i found an issue (on a production website!) where VoiceOver completely skips over consecutively nested display:contents elements inside shadow DOM.
I confirmed this in Safari 18.1.1 / macOS. I also confirmed it in Safari 18.1.1 / iPadOS except if I am careful I can get it to announce with explore-by-touch. But not via any other navigation method.
Update: 24 November 2024
Maybe don’t use display: contents
with web components if there is a chance you will have Safari visitors.
If an HTML
<script>
is placed inside a container which has thedisplay: contents;
CSS rule applied to it, VoiceOver unexpectedly announces the script’s content when the page is viewed in Safari.
Which means devs still have to code around Safari display property bugs:
I shared this issue on Mastodon and got various responses including some recommending avoiding
display: contents
entirely. I understand that sentiment given the difficulty testing the full matrix of OS x browser x screen reader combinations and the apparent flakiness of support fordisplay: contents
, but in a handful of cases it’s really really useful, so I think we can just proceed with caution and take extra care to test whenever we use it (and use it as a last resort).
I think it’s fair that he sums up display: contents
as useful, but also a last resort.
5 Comments
I encounter similar issues when I wish to set grid on the body element and display contents on the main element. The main issue I have is implementing a skip to content link that targets the main[display: contents] element :(
I think this should be of interest to the community since the following is a common DOM pattern:Skipping the main element would really be a shame
In response to .part of my comment was sanitized, so here is a demo that illustrates my point
https://codepen.io/WW3/pen/XWEVoqN
Thank you for posting this and for continuously testing for the current state of things.
display: contents
seems really valuable as CSS grid becomes more commonplace, but until some of these issues are fixed I’m still going to avoid grid entirely (where feasilbe) in cases wheredisplay: contents
would be necessary.
In response to .FWIW, I think an alternate approach might be to test the problematic instances on your audience’s browsers and then decide which cases you can ignore and which cases are problems. But I very much understand the frustration — I have been there for a few years now.
[…] from the accessibility tree in response to certain display properties, including display: none. It’s Mid-2022 and Browsers (Mostly Safari) Still Break Accessibility via Display Properties by Adrian Roselli covers this in more […]
Leave a Comment or Response