w3c / html-aria

ARIA in HTML
https://w3c.github.io/html-aria/
Other
181 stars 48 forks source link

Revise allowed roles/attributes on table elements #258

Open scottaohara opened 3 years ago

scottaohara commented 3 years ago

Presently we indicate that table elements can allow for any role, and while this makes sense in the context of the legacy issues of table misuse it's not really accurate for modern web development.

Additionally, there needs to be more clarity specifically for table descendants that "any role" is really only applicable if the immediate table ancestor is not exposed as a table or grid. For instance, the following is nonsense but presently throws no validation errors.

<table>
  <tbody role=article>...</tbody>
</table>

This issue closes #97

scottaohara commented 3 years ago

a table currently allows for any role. Per issue 97, that could be restricted to grid, treegrid and none/presentation.
Theoretically i agree with this, but for the legacy misuse of tables for layout purposes, which unfortunately is not a completely kicked bad habit. I've even recently seen some modern-day websites where tables were used unnecessarily for layout purposes.

That said, I think we could still tone down the "any role" to be a bit more reasonable. e.g., table role=button is a disgusting idea. More on this in a bit...

Regarding table children which also presently allow any role, which is also a bit much and should not be allowed when the ancestor table is still exposed as a table, here's a basic draft stub for such table children:

<strong class="nosupport">No `role`</strong> if the ancestor `table` is exposed as a `table`, `grid` or `treegrid`.
Otherwise, [ roles would be variable based on the element ]  

So for instance for this table content (and this is where table could get it's allowed roles from too) tbody, tr, etc. would have group/container based role allowances. Then th, td would have singular/child element based roles

@stevefaulkner @patrickhlauke further thoughts please?

JAWS-test commented 3 years ago

I think that at <table> only grid, treegrid and presentation should be allowed, because otherwise the expectation of what role the child elements have is unclear (even if it is regulated in the specification, many will not intuitively know this)

For all child elements of <table>, I would consider the following to be correct:

scottaohara commented 3 years ago

@JAWS-test regarding

"I think that at <table> only grid, treegrid and presentation should be allowed, because otherwise the expectation of what role the child elements have is unclear (even if it is regulated in the specification, many will not intuitively know this)"

As mentioned, i theoretically would agree with this if not for it making the remediation of legacy table layouts much more difficult.

per your second points about children of tables, agree on the second bullet as that's in my quick draft. Per your first bullet though, I think the spec can be a bit more reserved on any role. E.g., is there really a good reason for allowing <tbody role=button>, or <tr role=switch>?

JAWS-test commented 3 years ago

As mentioned, i theoretically would agree with this if not for it making the remediation of legacy table layouts much more difficult.

I'm afraid I don't understand that. If I have a layout table, I have to use role=presentation. But role=article should not be allowed. But I would still expect AT to interpret this incorrect markup like role=presentation at the table and additionally role=article.

E.g., is there really a good reason for allowing tbody role=button, or tr role=switch?

There is no good reason for it. But there is no good one against it either. From the logic of the specification, all roles should be allowed on elements that have no implicit role. Otherwise I could also say button is allowed on div, but not on span.

scottaohara commented 3 years ago

@JAWS-test that's not exactly correct. Yes, you can use role=presentation to force a table to not to be exposed as a table. but you could also do <table role=article> to expose the table as an article, and by suppressing the table semantics, all child elements lose their table semantics, similarly to if using role=presentation on the wrapping element. At least this behavior can be reproduced if you do what I mention in Chrome, Edge, Firefox and Safari.

regarding your second point, i don't agree with there not being definable cons that would dissuade being mindful of what's allowed on a table children, particularly those that are used solely to group rows/cells of potentially structured content. Yes, a similar argument could be made towards div.... but that would have to ignore how developers use the element for a wide variety of purposes. You cannot make that argument with tbody or tr...those are only valid within tables and you don't see developers using them for any odd thing in their web pages.

accessabilly commented 3 years ago

I want to bring up the following to reconsider the current ARIA spec for role attributes on table elements <td>, <th>, <tr>:

I'm currently using Adrian Roselli's technique for responsive tables: It "destroys" semantics of HTML table elements via CSS by setting them all to display: block to make the table look like a list thing in smaller breakpoints. It "repairs" it via implicit role attributes on all table elements (e.g. <td role="cell">).

The new ARIA spec allows no implicit role on the table elements <td>, <th>, <tr>. The HTML Validator returns this error (for <td>):

The role attribute must not be used on a td element which has a table ancestor with no role attribute, or with a role attribute whose value is table, grid, or treegrid.

This reflects the spec saying:

ARIA roles, states and properties which MAY be used: No role if the ancestor table element has role=table, grid, or treegrid; otherwise any role.

See Document conformance requirements for use of ARIA attributes in HTML

I would like to make a point to reconsider this. In my view it may be valid to disallow all other role attributes, when ancestor table is role="table". But why not let all implicit roles be ok here? Like <td role="cell">. It would be the only way to fix semantics that are previously broken via CSS (I tested this in Chrome & Firefox with NVDA). Adrian Roselli points out, that Safari breaks all semantics here.

scottaohara commented 3 years ago

It seems to me that there are two issues here.

  1. We can request the HTML validator remove the errors when using the implicit roles on the native HTML elements. For instance, there are other elements which indicate there are no allowed roles (details with implicit role=group), but that only surfaces a warning when used, not an error. Consistency with other treatments, and not producing both warnings and errors is definitely a good goal to have. Edit: request made
  2. These negating of the element mappings due to CSS changes is something that has been brought up before, and Firefox for example, has made some attempts to revise this behavior. Clearly it's not perfect, which is also understandable since there is a lot of table misuse baggage that the browsers and AT both have had to deal with and try to correct over the years. That said, it has been a long standing recommendation that authors specify role=presentation on a <table> to remove it's table semantics w/out the need to also set all descendants to role=presentation. If browsers are not respecting the inverse, where specifying a role=table on a <table> still requires all the descendant elements to have their implicit roles re-specified, then those are browser bugs that should be filed.

All that said, as the title of this issue states we will be looking at additional updates to table element rules for the next version of ARIA in HTML. If there are any additional rules or edits needed to existing element rules, we will definitely continue to review/take those into consideration.

Fenwick17 commented 2 years ago

Adding on to what was said by @accessabilly. At NHS we have a responsive table which works in a similar way to the Adrian Roselli tables. Where we use fixed roles to maintain the tables default roles despite the CSS changes.

This also leads to use getting numerous HTML validation errors such as The role attribute must not be used on a tr element which has a table ancestor with no role attribute, or with a role attribute whose value is table, grid, or treegrid. When all we do is add the default role for a tr.

Perhaps these could be changed to only cause the warning only for unncessary roles which it currently does, but ideally without the error. While the role is necessary here, I understand that this is based upon context, so the warning would still be acceptable.
Example of the validator error

scottaohara commented 2 years ago

Hi @Fenwick17 Thanks for the comment. The request for the validator to update has already been made (link in my last comment), so there's no more convincing needed here. The conformance checker is what needs to be updated now.

scottaohara commented 2 years ago

a recent issue has popped up with the html validator where what should have been allowed is being flagged: https://github.com/validator/validator/issues/1304

adding that here in lieu of the above discussion. need to take a new look at what's been done for resolving this issue, and re-review what was updated in the spec. we want to make sure that we aren't making anything invalid that isn't causing actual issues.

mitchellevan commented 1 year ago

Currently ARIA in HTML does not allow role="presentation" on <tr> or <td> descendants of role="table" et al.

These Firefox issues give code examples and explanations of why it should be allowed:

https://bugzilla.mozilla.org/show_bug.cgi?id=1257490 https://bugzilla.mozilla.org/show_bug.cgi?id=1832372

For comparison, <li> does allow role="presentation".

scottaohara commented 1 year ago

clarification: li does presently allow role=none, but that's also a bug in the current spec and will be addressed when this PR is implemented by another checker: https://github.com/w3c/html-aria/pull/410

mitchellevan commented 1 year ago

@scottaohara does the use case, which I cited above in Bugzilla, convince you that we should allow role="none" and presentation on <tr> and <td>?

I realize that a developer could make the mistake of role="none" on non-empty <td>. But that's no different from the following developer mistake, for which browser error handling is well defined:

<table>
  <tr>
    <th>Food</th>
    <th>Vegetable?</th>
  </tr>
  <tr>
    <th>cabbage</th>
    <td>yes</td>
  </tr>
  <span>Friendly reminder</span> <!-- developer mistake -->
  <tr>
    <th>tomato</th>
    <td>no</td>
  </tr>
</table>

I've commented #410.

mitchellevan commented 1 year ago

Two more possibilities:

scottaohara commented 1 year ago

But that's no different from the following developer mistake, for which browser error handling is well defined:

That's actually quite different in reality, as per your example, the HTML parser would kick out that errant span and render it in the DOM prior to the table element. The content would then be consistently accessible, and visually the developer would likely see their error as their content didn't appear in the table as they expected.

However, a cell which was set to role=none but had content would then remain in the rendered table, but be inconsistently inaccessible as the cell would no longer be reachable by someone using table navigation with their screen reader. One could reach that content if they did not use table navigation... but the practical discoverability of that would likely be low.

As per my comment in the li PR, on the surface your request make sense but the additional checks/implementation details would make the rule more complicated to implement, and in reality one can practically achieve what you're suggesting by using aria-hidden=true. role none/presentation already have so many checks for mitigating against author error in the ARIA spec, and one reason for this is because of using the role in situations where aria-hidden is the more appropriate/logical choice. I get that it achieves the effect that you've demonstrated, but there is a better attribute for that which is allowed and doesn't then make the rule more complicated to account for a narrowly scoped case where the role works without breaking things.

mitchellevan commented 1 year ago

one can practically achieve what you're suggesting by using aria-hidden=true

Good point, and thanks for the clear explanation. Now I'm fine with disallowing role="presentation" on <tr> and <td> descendants of table et al.