-
Notifications
You must be signed in to change notification settings - Fork 672
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
Comments
Why not treat it like when having a
|
In my opinion, such a warning should be placed with every problematic CSS property
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. |
Proposal:
|
The CSS Working Group just discussed
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. |
OK, we've edited this into css-display-3 in 7be289b
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. |
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 |
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 |
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:
Let's look at some test cases: 1: 2: 3: 4: 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. |
OK, we clarified the note. It now reads:
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 |
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 For aria-hidden, my understanding is that it is similar to |
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. |
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. |
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:
|
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 |
I don't feel like it is conceptually all that complicated. The real problem, in my mind, is that AT apparently treats With But Is that not a reasonable way to look at it? |
Your ideas sound good, unfortunately according to specification HTML AAM display:none, hidden, visbility:hidden and aria-hidden=true is equal |
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/ |
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 |
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 |
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. |
This isn't just AT. It's right throughout the entire stack: OS APIs, a11y specs, browsers, AT.
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.
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.
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.
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:
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.
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. |
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 |
@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? |
@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) |
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 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 |
I think there is a simple rule of thumb as to when visible content within invisible content is problematic:
|
I mostly agree, except for On the other hand, there can also be cases like tool tips where they start out as
Or it's text or picture data content. I guess those are children nodes but not children elements. But yes.
Yes, sometimes, but not always.
I think you meant
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.)
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 |
That makes more sense for |
I do not doubt you. On the other hand, I would guess that most pages that use |
This already happens for cases where a container accessible is given an incompatible role. For example, if you do this: 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.
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. |
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
The text was updated successfully, but these errors were encountered: