Test 387: One or more table elements that hold table data, without an
ARIA-assigned role, not intentionally hidden in the DOM and available to assistive technologies, does not
contain one or more th elements (without an ARIA-assigned role); th elements with a
role set to rowheader | columnheader; or td elements with a role set to
rowheader | columnheader.
The markup pipeline propagated role="none"/role="presentation" to every
descendant of the presentational element. A table wrapped in <div role="none">
therefore had its th elements marked as unavailable to assistive technology, so test 387 found no
headers and false-flagged the table. Reported from a client's Blazor application, where a focus-trap wrapper
carries role="none" around the whole modal.
Presentational roles are inherited only by an element's required owned elements, not by
arbitrary DOM descendants. A <div> has no required owned elements, so
role="none" on it strips the semantics of the div and nothing else - the
<table> inside starts a fresh semantic context and keeps its rows, headers and cells. Only
<table role="none"> cascades, along table → rowgroup → row → columnheader.
Confirmed against VoiceOver and NVDA, which both announce the headers below.
Expected after the fix: the orange Bug cases must no longer be flagged by test
387, and the red Fail cases must still be flagged - the cascade has to keep working where ARIA says
it applies, so this is not a matter of exempting tables under role="none".
| Header 1 | Header 2 |
|---|---|
| Data 1 | Data 2 |
| Data 3 | Data 4 |
A div owns no required elements, so the th elements stay available to AT.
| Header 1 | Header 2 |
|---|---|
| Data 1 | Data 2 |
role="none" and role="presentation" are ARIA synonyms, so this must behave identically to the case above.
Several levels of role="none" wrappers, none of which owns the table.
|
The cascade reaches the outer table's cell and stops: a cell owns nothing, so the nested data table keeps its headers.
| Airi Satou | Accountant | Tokyo |
| Angelica Ramos | Chief Executive Officer | London |
Regression guard: the fix must not blanket-exempt tables under role="none".
| Name | Age |
|---|---|
| Airi Satou | 33 |
A row does own its cells, so the presentational row correctly strips these th elements and the table is left with no headers available to AT.
| Header 1 | Header 2 |
|---|---|
| Data 1 | Data 2 |
The table has an ARIA-assigned role and is not available to AT, so it is outside the candidate set.
| Header 1 | Header 2 |
|---|---|
| Data 1 | Data 2 |
The symmetric case to the wrapper: when the role is on the table itself the cascade does apply, stripping the th elements. This is N/A rather than a fail, because test 387 only evaluates tables that are themselves available to AT and carry no ARIA role.
Intentionally hidden in the DOM, so it is not evaluated.