Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For the Accessibility API visibility:visible within visibility:hidden is problematic #6123

Open
JAWS-test opened this issue Mar 20, 2021 · 30 comments
Labels
a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. Closed Accepted by CSSWG Resolution Commenter Response Pending CSS2 css-display-3 Current Work css-display-4

Comments

@JAWS-test
Copy link

https://drafts.csswg.org/css2/#visibility defines that I can make invisible areas (visibility:hidden) visible with visibility:visible.

The invisible areas do not show up in the browsers Accessibility API tree. The visible ones do. This causes certain nested elements to become invalid for the API (e.g. table cells without a table, because the table is marked with visibility:hidden, but the table cells are marked with visibility:visible).

I suggest to include a warning in the specification that visibility:visible must not be used with nested elements.

Otherwise, there will be a broken tree in the Accessibility API and incorrect output from screen readers

@Loirooriol
Copy link
Contributor

Why not treat it like when having a display: table-cell with a display: block parent, if that's not broken? But probably that's also broken, which would hint that this isn't actually a visibility problem.

visibility was designed as an inherited property with the ability to be overridden in descendants. IMO the statement that you are proposing doesn't seem enforceable nor web compatible.

@JAWS-test
Copy link
Author

JAWS-test commented Mar 21, 2021

@Loirooriol

Why not treat it like when having a ...

In my opinion, such a warning should be placed with every problematic CSS property

display: table-cell with a display: block parent, if that's not broken?

No. In no browser that I know of, nor according to the specification, does display have any effect on the Accessibility API tree (except, of course, display:none). I.e. neither display:block turns a table into a non-table nor display:table-cell turns a non-table element into a table cell. There is only Chrome's decision to submit a table, fully created with all table property of CSS, as a layout table to the Accessibility API. However, this is firstly not a data table and secondly the tree is not broken by this, since it is submitted as a full table. Furthermore, I think this is a bug of the browser (FreedomScientific/standards-support#344).

Furthermore, there are problems with display:contents at tables. However, these are also browser bugs that have been fixed for example by Chrome in the meantime (https://adrianroselli.com/2018/02/tables-css-display-properties-and-aria.html). But even these bugs never caused the Accessbility API tree to be broken, they only caused a table to not be output as a table. The tree itself was correct in itself.

@fantasai fantasai added a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. css-display-3 Current Work css-display-4 CSS2 labels Mar 23, 2021
@fantasai
Copy link
Collaborator

fantasai commented Aug 5, 2021

Proposal:

  • Import 'visibility' from CSS2 to css-display-3 (since it is currently only defined in CSS2).
  • Define impact of visibility: hidden similar to display: contents (shouldn't strip necessary a11y information from the tree).
  • Add a warning to authors that marking a required structural parent box as invisible while descendants are visible (e.g. table-row invisible while table-cell is visible) can be problematic.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed visibility: visible and a11y, and agreed to the following:

  • RESOLVED: accept proposal
The full IRC log of that discussion <fantasai> Topic: visibility: visible and a11y
<fantasai> github: https://github.com//issues/6123
<fantasai> TabAtkins: some a11y folks brought up that the visibility property is tricky
<fantasai> TabAtkins: in particular, visibility:hidden on visibility:visible ancestor
<fantasai> TabAtkins: problem is invisible items gets stripped from a11y tree
<fantasai> TabAtkins: very similar to 'display:contents' a11y bug
<fantasai> TabAtkins: our proposal is to specify impact of 'visibility:hidden' as similar to 'display:contents'
<fantasai> TabAtkins: wrt a11y
<fantasai> TabAtkins: to do that, pull visibility property definition from CSS2 to css-display-3
<fantasai> TabAtkins: and add a warning to authors that in special cases (like tables) can cause problems to have invisible ancestor of visible child
<fantasai> TabAtkins: this proposal got a thumbs up from the original commenter
<fantasai> florian: ...
<fantasai> florian: unlike table cell example, what if these hidden boxes have text content?
<fantasai> florian: do we retain the box but not the text, or what
<fantasai> TabAtkins: text isn't an issue here, because invisible to everyone
<fantasai> TabAtkins: it's the implicit structural relationships that shouldn't get lost
<fantasai> florian: so text shouldn't be in box tree either, just the box structure
<fantasai> TabAtkins: yes
<fantasai> Rossen_: referring to text inside cell made visible?
<fantasai> TabAtkins: no, invisible text
<florian> s/in box tree either/in accessibility tree either/
<fantasai> Rossen_: so text inside of other cells
<fantasai> florian: that, or if div with text in it that's hidden, and span that's visible
<fantasai> florian: do we hide all the text outside the span
<fantasai> Rossen_: yes, this is expected behavior and implemented
<fantasai> florian: is it implementable
<fantasai> fantasai: shouldn't be any problem, text has its own boxes in implementations
<fantasai> Rossen_: ...
<fantasai> Rossen_: text for role/description can be taken from hidden areas, but that's a known pattern that works
<fantasai> Rossen_: current implementations already support display of visible text inside of hidden elements
<fantasai> Rossen_: the issue is only when there's structure part of the invisible elements, then want to be able to recreate that
<fantasai> Rossen_: Tab, one question I have is
<fantasai> Rossen_: the use case here is very specific to when a table has visibility:hidden and cell is visibility:visible
<fantasai> Rossen_: is the same behavior here, are we trying to specify same for table which is inside of visibility:hidden?
<fantasai> TabAtkins: I don't believe the issue is specific to that
<fantasai> TabAtkins: applies the same if you visibility:hidden a link, and visibility:vissible some contents of the link
<fantasai> TabAtkins: We don't want that to strip the linkness of the text inside which is still visible
<fantasai> Rossen_: ok, didn't want to make it too specific
<fantasai> fantasai: no, going to make it quite general
<fantasai> proposal is https://github.com//issues/6123#issuecomment-893890561
<fantasai> Rossen_: so expected behavior is to provide the structural role of the invisible ancestors of visible elements in the a11y tree
<fantasai> TabAtkins: yes, same as display:contents
<fantasai> Rossen_: anything else?
<fantasai> fantasai: we're pulling visibility propdef from CSS2 to css-display-3 (not defined anywhere else than CSS2 atm)
<fantasai> Rossen_: hearing no objections here
<fantasai> RESOLVED: accept proposal
<fantasai> Meeting closed.
<Rossen_> Zakim, end meeting
<Zakim> As of this point the attendees have been plinss, argyle, jensimmons, GameMaker, emilio, Rossen_, dlibby, smfr, TYLin, sanketj, jfkthame, bradk, dholbert, vmpstr, futhark, tantek
<Zakim> RRSAgent, please draft minutes v2
<RRSAgent> I have made the request to generate https://www.w3.org/2021/08/11-css-minutes.html Zakim
<Zakim> I am happy to have been of service, Rossen_; please remember to excuse RRSAgent. Goodbye
<iank_> TabAtkins: I can VC today - but out the next two days.

@fantasai
Copy link
Collaborator

OK, we've edited this into css-display-3 in 7be289b

  • Copied over property definition from CSS2.
  • Added a note about potential accessibility problems with visible-in-invisible constructs applied to strict structures.
  • Defined invisibility to also imply removal of interactivity and navigability, not just rendering.
  • Added a note about interaction with the 'speak' property in css-speech-1.
  • Generalized the definition of collapse to include collapsed flex items as well as tables, and to allow additional special behavior to be defined in other layout specs.

The new section can be seen at https://drafts.csswg.org/css-display-3/#visibility

We'd appreciate a review, and any suggestions for improved clarity! These edits will then go into the next CR publication.

@bradkemper
Copy link
Contributor

If "their semantic role as a container is [truly] not affected, to ensure that any visible descendants are properly interpreted", then the note about the table cells shouldn't really apply, should it? Or is that only about legacy screen readers that aren't keeping the semantic role of the hidden parent elements?

Also: the note could really use some commas. I had a hard time navigating that first sentence of the note.

Also: I think it isn't just parent relationships that need to be considered. A label element with a for attribute should also retain its semantics when invisible, for example, IMHO.

@JAWS-test
Copy link
Author

JAWS-test commented Aug 13, 2021

However, as with display: contents, their semantic role as a container is not affected, to ensure that any visible descendants are properly interpreted.

Like @bradkemper, I don't understand this: either the role of invisible elements is preserved or not. If it is preserved, the accessibility warning is not needed.

However, it is currently the case that in the browsers I have tested, the role of invisible elements is not preserved, so the screen reader does not output the visible child elements with their correct role either. In Chrome, for example, this leads to the strange behavior that table cells are output, but no table, and no table navigation is possible. See https://codepen.io/jaws-test/pen/eYWXypB

@jcsteh
Copy link

jcsteh commented Aug 18, 2021

I understand the use case here. However, I worry there are a lot of edge cases where the expected behaviour is now unclear. Unlike display: contents, visibility: hidden affects descendants. That raises a lot of questions about what should remain in the tree, what shouldn't and what should happen during certain mutations:

  • What's defined as a container that should remain in the tree and what isn't?
  • What about text nodes inside those invisible containers?
  • If the stuff inside the tree suddenly gets hidden too, are we supposed to prune the whole tree?

Let's look at some test cases:

1:
data:text/html,<p style="visibility: hidden;"><button>hello</button> <button style="visibility: visible;">world
Should hello (or its containing button) be exposed?

2:
data:text/html,<p style="visibility: hidden;"><button>hello <img style="visibility: visible;" src="https://via.placeholder.com/10x10.png" alt="messed up"></button> <button style="visibility: visible;">world
The "messed up" image should certainly be in the tree, but what about its parent button? The button has semantic relevance, yet you can't focus it or activate it, so exposing it seems wrong.

3:
data:text/html,<table style="visibility: hidden;"><tr id="tr" style="visibility: visible;"><th>hello <button onclick="tr.style.visibility = 'hidden'">broken world</button></th></tr></table>
When the tree is initially rendered, the new rule says the table should be exposed. But what happens when you press the button? Does the whole table get removed from the tree or just the row?

4:
data:text/html,<table style="visibility: hidden;"><tr id="tr" aria-hidden="true" style="visibility: visible;"><th>hello <button onclick="tr.removeAttribute('aria-hidden');">broken world</button></th></tr></table>
The new rule says the table should be exposed because of the visible child. But the visible child is aria-hidden. So should the table be exposed or not? And when you press the button and aria-hidden gets removed, does the table magically spring into existence?

These are just the cases I was able to come up with off the top of my head. I fear there are a lot more.

@fantasai
Copy link
Collaborator

fantasai commented Sep 3, 2021

OK, we clarified the note. It now reads:

Note: Currently, many user agents and/or accessibility tools don't correctly implement the accessibility implications of visible elements with semantic relationships to invisible elements, so, for example, making parent elements with special roles (such as table rows) invisible while leaving child elements with special roles (such as table cells) visible can be problematic for users of those tools. Authors should avoid creating these situations until the tooling situation improves.

@jcsteh

For case 1, no, neither “hello” nor its containing button should be exposed, because they are hidden.

For case 2, the presence of the image should imply the presence of its containing button, allowing it to be focused and activated.

For case 3, CSS is stateless, so the entire tree is hidden just as if it were originally that way.

For case 4, I think this gets even deeper into undefined territory: afaik there isn't a clear mapping spec for the implications of CSS on the accessibility tree (and it's out of scope for css-display), but effects of visibility and aria-hidden should probably combine to hide the entire tree there. And again, the document is stateless so scripting the addition or removal of the attribute should be no different than loading a fresh document in that state. (It may be trickier to implement, though.)

Note: All of these should be identical to the same situations with display: contents, so the answers should be the same as for that (or are equally undefined currently...)

@bradkemper
Copy link
Contributor

I'm not sure I agree with that being the best thing to do for case 2, though I guess it fits with the current text. It seems a little weird and unexpected to me.

I think instead of "their semantic role as a container is not affected", it should be "their semantic role in relation to other elements is not affected". Thus, a hidden button would not have a semantic role of its own, even with a visible child. But a TD would still reference a hidden TH in a hidden THEAD, and behave as though its parent table parts are not hidden, for the sake of giving meaning to the TD (almost like how table fix up occurs when a parent table part is missing, but referencing the actual structures present instead of creating new ones). And aria-labelledby would still work to get that label even if the thing it was labeled by was visibility: hidden (but not if it was display:none). But if the table-row had visibility: hidden and tabindex="0", you still wouldn't be able to focus it, because it is hidden.


For aria-hidden, my understanding is that it is similar to display none, in that it completely removes it and its children from the accessibility tree (as completely as display none removes it from the render box tree). So visibility property shouldn't matter at that point.

@bradkemper
Copy link
Contributor

The note part is better than the definition part, because the note speaks to "the accessibility implications of visible elements with semantic relationships to invisible elements". That is better than implying that all semantics, focusability, etc. of an element are retained if it has a visible descendant.


A text node child of a hidden element should also remain invisible, even if there are other visible descendants.

@JAWS-test
Copy link
Author

@fantasai

Note: Currently, many user agents and/or accessibility tools don't correctly implement the accessibility implications of visible elements with semantic relationships to invisible elements, ...

I do not think this phrasing is correct. If I had thought that the CSS specification was correct and only the browsers or the screen readers were doing it wrong, I would have posted a ticket for the browsers or the screen readers. However, I think the problem is in the CSS specification and that's why I opened the ticket here. How should the browsers and screen readers correctly handle visible content within invisible content? There is no good solution for this and that's why I would actually be in favor of abolishing the possibility of nesting visible content within invisible content. However, this is probably not possible and therefore there should be an appropriate warning, but not blaming the browsers or screen readers.

@bradkemper
Copy link
Contributor

@JAWS-test

How should the browsers and screen readers correctly handle visible content within invisible content? There is no good solution

I think this spec is making good strides towards specifying reasonable solutions that might have been under specified before. But maybe the note could be reworded a bit, to eliminate the blaming tone. How about:

Note: Currently, many user agents and/or accessibility tools don't maintain the semantic relationship/connection of visible elements with invisible elements, ...

@JAWS-test
Copy link
Author

JAWS-test commented Sep 10, 2021

@bradkemper

I think this spec is making good strides towards specifying reasonable solutions that might have been under specified before

Unfortunately, I cannot agree with this. I think that for accessibility, for technical reasons, no good solution exists for visible elements nested within invisible elements. I don't know what such a solution should look like. And the current version of the specification doesn't offer a solution either. That's why I don't think user agents or assistive technology can fix the problem, which is one of the CSS specification, so I still think your softened suggestion is wrong.

But I don't want to argue further about the correct wording. The most important thing for me is that a corresponding warning is included in the specification. If this is achieved, I am satisfied

@bradkemper
Copy link
Contributor

I don't feel like it is conceptually all that complicated. The real problem, in my mind, is that AT apparently treats visibility: hidden and display: none as though they mean the same thing, when they were never meant to be in CSS.

With display: none, it effectively removes the element from the tree (the render tree and a11y tree), thereby also removing all its descendent branches with it.

But visibility: hidden isn't supposed to do that. It is only making that one element or pseudo-element (including its text nodes) completely transparent, without affecting descendant elements except through inheritance. It still abides in the render tree, and should also still abide in the a11y tree. So, in my mind, the equivalent for screen readers is that it shouldn't be read aloud, but it should still maintain its meaning and structure and place in the tree. It should still directly traversable. And, because it is still tree-abiding, it should also be available for giving meaning to related table structures, or to providing labels through for and aria-lablelledby, or to providing description via aria-describedby. If the element had no visible descendants and no descendants that acted as labels or table headers, etc., then it could be treated the same as display: none or aria-hidden="true", because only then is the element and its descendants both empty and meaningless.

Is that not a reasonable way to look at it?

@JAWS-test
Copy link
Author

@bradkemper

Your ideas sound good, unfortunately according to specification HTML AAM display:none, hidden, visbility:hidden and aria-hidden=true is equal

@JAWS-test
Copy link
Author

@bradkemper

Please note that with respect to aria-labelledby and aria-describedby, visibility:hidden does not behave differently from display:none or hidden, i.e. invisible elements can be used as labels or descriptions as long as they are referenced, see: https://www.w3.org/TR/accname-1.1/

@bradkemper
Copy link
Contributor

Your ideas sound good, unfortunately according to specification HTML AAM display:none, hidden, visbility:hidden and aria-hidden=true is equal

Yeah, but it shouldn't be, in my view, as that is contrary to how visibility has always been defined in CSS. Working Drafts can be changed. Can AT, in a way that doesn't disrupt existing pages, by still hiding branches in which all descendants are visibility: hidden?

@JAWS-test
Copy link
Author

@bradkemper

My suggestion would be: If the CSS specification assumes that visibility:hidden only hides the content but leaves the semantic structure (roles) untouched, then a corresponding ticket should be posted at Accname, HTML AAM and ARIA by those who hold this view.

Related: w3c/aria#1055 and w3c/accname#57

@bradkemper
Copy link
Contributor

Please note that with respect to aria-labelledby and aria-describedby, visibility:hidden does not behave differently from display:none or hidden, i.e. invisible elements can be used as labels or descriptions as long as they are referenced, see: https://www.w3.org/TR/accname-1.1/

Ah, I stand corrected on that point at least then. My (possibly faulty) remembrance of w3c/aria-practices#1136 (comment) was making me think otherwise. Or is aria-hidden different from display:none in that regard? Anyway, that issue is 2 years old too, so things may have changed since then.

@jcsteh
Copy link

jcsteh commented Sep 14, 2021

I don't feel like it is conceptually all that complicated. The real problem, in my mind, is that AT apparently treats

This isn't just AT. It's right throughout the entire stack: OS APIs, a11y specs, browsers, AT.

visibility: hidden and display: none as though they mean the same thing, when they were never meant to be in CSS.

Maybe they're not the same in CSS, but CSS is also not primarily focused on semantics. So, a11y had to come up with a semantically appropriate mapping. That mapping has been this way for decades.

But visibility: hidden isn't supposed to do that. It is only making that one element or pseudo-element (including its text nodes) completely transparent, without affecting descendant elements except through inheritance.

The fact that it is inherited is hugely relevant for a11y. That means an entire subtree could be "invisible" to sighted users. Sites in the wild (e.g. Google Help Panel) use visibility: hidden to hide entire sections of a page from sighted users.

It still abides in the render tree, and should also still abide in the a11y tree. So, in my mind, the equivalent for screen readers is that it shouldn't be read aloud, but it should still maintain its meaning and structure and place in the tree.

But the a11y tree isn't the render tree. It does not have a concept of "an entire subtree which is in the tree but shouldn't be read". Furthermore, "shouldn't be read aloud" and "should still maintain its meaning" are incompatible concepts for a11y. If it has meaning, it should be read. Otherwise, it shouldn't be exposed. Again, this is how a11y works and has always worked. You can argue that's wrong, but unless we have a path to change an entire industry and stack, that's not a pragmatic argument.

If the element had no visible descendants and no descendants that acted as labels or table headers, etc., then it could be treated the same as display: none or aria-hidden="true", because only then is the element and its descendants both empty and meaningless.

And herein lies the problem. The proposal here requires that whenever a visibility: hidden element is encountered, browser a11y engines must do one of three things:

  1. Crawl the entire subtree first to determine whether there is a visible descendant.
  2. Skip hidden nodes as they do now, and then if a visible descendant is found, retrospectively add the ancestors they skipped.
  3. Include all nodes in the tree and somehow filter them out before returning them to the a11y client.

To make things even more complicated, we also have to figure out how to handle mutations. If a visible descendant gets added or removed, we have to do the whole calculation again, potentially rebuilding or throwing away massive parts of the tree.

At least for Firefox (speaking as the tech lead for Firefox a11y), any of these solutions is a massive undertaking and involves significant risk of potentially catastrophic regressions.

Note: All of these should be identical to the same situations with display: contents, so the answers should be the same as for that (or are equally undefined currently...)

Perhaps visibility: hidden and display: contents are conceptually similar in terms of layout implementation, but they are very different semantically. display: contents is a very clear message: this is semantically relevant but not visually relevant. In contrast, visibility: hidden is often used to hide entire parts of a page visually, so it is not necessarily saying "this is semantically relevant". It depends on the subtree, which is where things get really nasty as outlined above.

@JAWS-test
Copy link
Author

@bradkemper

Or is aria-hidden different from display:none in that regard?

I don't know exactly myself, because on the one hand it's very complex and on the other hand it's currently being updated

@fantasai
Copy link
Collaborator

@JAWS-test Your original comment was about visible descendants of invisible ones being problematic for AT if the invisible ones had important relationships to the visible descendants. Your latest comment seems to imply that any visible descendant of an invisible one is problematic for AT. That's a much bigger scope of “things that must not be done” than you originally asked for, why the scope change?

@JAWS-test
Copy link
Author

@fantasai Unfortunately, this is a misunderstanding. In most cases, visible content within invisible content is not a problem. Only in a few cases, as mentioned in my first comment, it is problematic, namely exactly when nested elements are used that need each other mandatory (like table, tr, th)

@SelenIT
Copy link
Collaborator

SelenIT commented Sep 14, 2021

they are very different semantically. display: contents is a very clear message: this is semantically relevant but not visually relevant. In contrast, visibility: hidden is often used to hide entire parts of a page visually, so it is not necessarily saying "this is semantically relevant".

I would say that there can still be probably more similarity than fundamental difference between these situations. Authors (at least those who care about semantics) don't often use CSS only to mark parts of content "semantically not relevant". In my opinion, the true message behind display: contents is usually "this particular thing may be not visually relevant, but its children definitely are"; the message behind making a thing not visible while still being part of layout and probably having visible descendants sounds more like "this particular thing may be not visually relevant (now), but some of its descendants probably are". If an educated author's intent is to mark the entire piece of the page as both visually and semantic not relevant, they would likely use display:hidden display:none or the HTML hidden attribute instead.

That said, I agree that accurate repesentation of this implied message is difficult. Moreover, difficuilties can be different in these cases related to different layout limitation. For example, a table with visibility: hidden that has several visibility: visible cells still looks much like a table (though some its cells are missing), so, as an AT user, ideally I would like it to be presented like "Table, N rows, M columns, only X cells are visible. Row A, column B: ..." and so on, and also would like to be able to navigate between visible cells using table navigation keys the same way as it happens in the table with some cells merged (I don't really expect it to be ever implemented that way, it's just my dream behavior 😀). In contrast, if the rows of the table have display: contens and their cells are displayed as a single row, it would likely be better to present them as a single row in the A11Y tree (and I'm not sure if it's possible without "fixing" the A11Y tree with "virtual" role="row" wrappers similarly to how CSS "fixes" the layout tree with anonymous boxes).

@JAWS-test
Copy link
Author

I think there is a simple rule of thumb as to when visible content within invisible content is problematic:
Remove all invisible content from the source code and leave all visible content in the source code. Check with a syntax checker whether the source code is valid:

  • it is still valid: no problem for accessibility
  • It is no longer valid: probably a problem for accessibility.

@bradkemper
Copy link
Contributor

Authors (at least those who care about semantics) don't often use CSS only to mark parts of content "semantically not relevant".

I mostly agree, except for display: none, which is used to completely remove something that is not currently relevant, but may be later, when it is shown by giving it some other display type. For instance an empty dialogue structure that exists as hidden scaffolding, but not part of the layout until it is filled in with content and then shown.

On the other hand, there can also be cases like tool tips where they start out as display: none until hovered, but could have meaning for AT even when not hovered (aria-describedby would work well with those, if that worked when referencing display: none elements).

In my opinion, the true message behind display: contents is usually "this particular thing may be not visually relevant, but its children definitely are";

Or it's text or picture data content. I guess those are children nodes but not children elements. But yes.

the message behind making a thing not visible while still being part of layout and probably having visible descendants sounds more like "this particular thing may be not visually relevant (now), but some of its descendants probably are".

Yes, sometimes, but not always.

If an educated author's intent is to mark the entire piece of the page as both visually and semantic not relevant, they would likely use display:hidden or the HTML hidden attribute instead.

I think you meant display: none. I would agree.

That said, I agree that accurate repesentation of this implied message is difficult. Moreover, difficuilties can be different in these cases related to different layout limitation. For example, a table with visibility: hidden that has several visibility: visible cells still looks much like a table (though some its cells are missing), so, as an AT user, ideally I would like it to be presented like "Table, N rows, M columns, only X cells are visible. Row A, column B: ..." and so on, and also would like to be able to navigate between visible cells using table navigation keys the same way as it happens in the table with some cells merged (I don't really expect it to be ever implemented that way, it's just my dream behavior 😀).

Yes, that seems like very reasonable behavior, from my perspective. (Disclosure: I am sighted and don't use AT myself except to test my pages for a11y.)

In contrast, if the rows of the table have display: contens and their cells are displayed as a single row, it would likely be better to present them as a single row in the A11Y tree (and I'm not sure if it's possible without "fixing" the A11Y tree with "virtual" role="row" wrappers similarly to how CSS "fixes" the layout tree with anonymous boxes).

Agreed. That is what I was alluding to earlier when talking about visibility, that some sort of fix up could happen for a11y like it does for CSS. The same sort of fix up should happen if the table row was given some other role, like role="dialog", but the cells still had their cell role. This gets beyond just CSS, but seems like what WCAG and AT and UAs should be working towards, rather than just saying we have to keep it a certain way because it's been that way for decades.

@bradkemper
Copy link
Contributor

I think there is a simple rule of thumb as to when visible content within invisible content is problematic:

Remove all invisible content from the source code and leave all visible content in the source code. Check with a syntax checker whether the source code is valid:

That makes more sense for display: none than for visibility: hidden. Or would if AT etc. we're interpreting visibility: hidden in a way that was more closely equivalent to how it is used for visual display.

@bradkemper
Copy link
Contributor

At least for Firefox (speaking as the tech lead for Firefox a11y), any of these solutions is a massive undertaking and involves significant risk of potentially catastrophic regressions.

I do not doubt you.

On the other hand, I would guess that most pages that use visibility: hidden, or responsive tables with display values that change for narrow layouts and hide the theads (none of which should change the semantics), and a lot of other things are just plain broken for a11y when (most) web authors don't take enough special care to try to work around some of the surprising things CSS can do to a11y. I don't mean to disparage your work, but it seems like there is a lot of opportunity to improvement for how CSS and a11y interact and intersect, and perhaps some of it could be done incrementally.

@jcsteh
Copy link

jcsteh commented Sep 15, 2021

That is what I was alluding to earlier when talking about visibility, that some sort of fix up could happen for a11y like it does for CSS. The same sort of fix up should happen if the table row was given some other role, like role="dialog", but the cells still had their cell role. This gets beyond just CSS, but seems like what WCAG and AT and UAs should be working towards,

This already happens for cases where a container accessible is given an incompatible role. For example, if you do this:
<table role="dialog"><tr><td>hi</td></tr></table>
Firefox doesn't expose row or cell.

The reason this case is much more complicated is that invisible things don't exist in the a11y tree at all. As I explained in #6123 (comment), "fixing" the tree in this case would require some pretty expensive crawling and book keeping.

rather than just saying we have to keep it a certain way because it's been that way for decades.

If I read you correctly, you're trivialising the concerns here, which seems pretty unreasonable to me. I'm not saying we should keep something the same way forever "just because". I'm saying that there is a great deal of implementation complexity and regression risk associated with this change (as well as unclear behaviour for various edge cases) that doesn't seem to have been taken into consideration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. Closed Accepted by CSSWG Resolution Commenter Response Pending CSS2 css-display-3 Current Work css-display-4
Projects
None yet
Development

No branches or pull requests

7 participants