Tests on Presentational role Conflict resolution - act-rules/act-rules.github.io GitHub Wiki

According to https://www.w3.org/TR/wai-aria-1.1/#conflict_resolution_presentation_none elements with a role of presentation/none must nonetheless be exposed with their implicit role if they have a global aria-* property (e.g. aria-label), or if the are focusable "or otherwise interactive" (not clear what that means).

There does not seem to be a similar official conflict resolution for aria-hidden elements, but some browsers seem to do it anyway…

Test time!

Chrome Version 80.0.3987.122 (Official Build) (64-bit) Edge build 18362 Firefox 73.0.1 (64-bit) NVDA 2019.3.1

Heading (implicit role, not focusable by default)

  • <h1 role="none">none</h1> C, E, F: not exposed (good)
  • <h1 aria-hidden="true">hidden</h1> C, E, F: not exposed (good)
  • <h1 role="none" aria-label="none+label">none+label</h1> C, F: exposed (good because global aria-*) E: not exposed (bad)
  • <h1 role="none" tabindex=0>none+Positive tabindex</h1> C, F: exposed (good because focusable) E: exposed with a role of none
  • <h1 role="none" tabindex=-1>none+Negative tabindex</h1> C, F: exposed (good because focusable) E: exposed with a role of none
  • <h1 role="none" aria-label="none+label+hidden" aria-hidden="true">none+label+hidden</h1> C, E, F: not exposed (bad? because global aria-*)
  • <h1 role="none" tabindex=0 aria-hidden="true">none+Positive tabindex+hidden</h1> C: exposed (good? because focusable) E, F: not exposed (bad?)
  • <h1 aria-label="label+hidden" aria-hidden="true">label+hidden</h1> C, E, F: not exposed (bad? because global aria-*)
  • <h1 tabindex=0 aria-hidden="true">Positive tabindex+hidden</h1> C: exposed (good? because focusable) E, F: not exposed (bad?)

List item (implicit role, not focusable by default)

  • <li role="none">none</li> C, E, F: not exposed (good)
  • <li aria-hidden="true">hidden</li> C, E, F: not exposed (good)
  • <li role="none" aria-label="none+label">none+label</li> C, F: exposed (good because global aria-*) E: not exposed (bad)
  • <li role="none" tabindex="0">none+positive tabindex</li> C, F: exposed (good because focusable) E: exposed with a role of none
  • <li role="none" tabindex="-1">none+negative tabindex</li> C, F: exposed (good because focusable) E: exposed with a role of none
  • <li role="none" aria-label="none+label+hidden" aria-hidden="true">none+label+hidden</li> C, E, F: not exposed (bad? because global aria-*)
  • <li role="none" tabindex="0" aria-hidden="true">none+tabindex+hidden</li> C: exposed (good? because focusable) E, F: not exposed (bad?)
  • <li aria-label="label+hidden" aria-hidden="true">label+hidden</li> C, E, F: not exposed (bad? because global aria-*)
  • <li tabindex="0" aria-hidden="true">positive tabindex+hidden</li> C: exposed (good? because focusable) E, F: not exposed (bad?)

Button (implicit role, focusable by default, in sequential focus order)

  • <button role="none">none</button> C, F: exposed (good? because focusable) E: exposed with a role of none
  • <button aria-hidden="true">hidden</button> C: exposed (good? because focusable) E, F: not exposed (bad?)
  • <button role="none" aria-label="none+label">none+label</button> C, F: exposed (good because focusable and global aria-*) E: exposed with a role of none
  • <button role="none" tabindex="0">none+postive tabindex</button> C, F: exposed (good because focusable) E: exposed with a role of none
  • <button role="none" tabindex="-1">none+negative tabindex</button> C, F: exposed (good because focusable) E: exposed with a role of none
  • <button role="none" aria-label="none+label+hidden" aria-hidden="true">none+label+hidden</button> C: exposed (good? because focusable) E, F: not exposed (bad?)
  • <button role="none" aria-hidden="true">none+hidden</button> C: exposed (good? because focusable) E, F: not exposed (bad?)
  • <button role="none" disabled>none+disabled</button> C, E, F: not exposed (good)
  • <button role="none" disabled aria-label="none+disabled+label">none+disabled+label</button> C, F: exposed (good because global aria-*) E: not exposed (bad?)
  • <button disabled aria-hidden="true">disabled+hidden</button> C, E, F: not exposed (good)
  • <button aria-label="label+disabled+hidden" disabled aria-hidden="true">label+disabled+hidden</button> C, E, F: not exposed (bad? because global aria-*)

Link (implicit role, focusable by default, in sequential focus order)

  • <a href="#" role="none">none</a> C, F: exposed (good? because focusable) E: exposed with a role of none
  • <a href="#" role="none" aria-hidden="true">none+hidden</a> C: exposed (good? because focusable) E, F: not exposed (bad?)
  • <a href="#" aria-hidden="true">hidden</a> C: exposed (good? because focusable) E, F: not exposed (bad?)

iframe (no implicit role, focusable by default, not in sequential focus order)

  • <iframe srcdoc="nothing"></iframe> C: exposed, role of "IFrame" E: exposed, no role F: exposed, role of "internal frame"
  • <iframe srcdoc="none" role="none"></iframe> C: exposed, role of "IframePresentational" E: exposed, role of none F: exposed, role of "internal frame"
  • <iframe srcdoc="hidden" aria-hidden="true"></iframe> C: exposed, role of "Iframe" E, F: not exposed
  • <iframe srcdoc="none+label" role="none" aria-label="none+label"></iframe> C: exposed, role of "IframePresentational" E: exposed, role of none F: exposed, role of "internal frame"
  • <iframe srcdoc="none+tabindex" role="none" tabindex="0"></iframe> C: exposed, role of "IframePresentational" E: exposed, role of none F: exposed, role of "internal frame"
  • <iframe srcdoc="none+label+hidden" role="none" aria-label="none+label+hidden" aria-hidden="true"></iframe> C: exposed, role of "IframePresentational" E, F: not exposed
  • <iframe srcdoc="none+hidden" role="none" aria-hidden="true"></iframe> C: exposed, role of "IframePresentational" E, F: not exposed

Images (additional fun with alt attribute on top of the rest)

  • <img src="#" role="none" /> C, E, F: not exposed (good)
  • <img src="#" aria-hidden="true" /> C, E, F: not exposed (good)
  • <img src="#" alt="" /> C, E: not exposed (good) F: exposed because does not respect alt="" (bad)
  • <img src="#" role="none" aria-label="none+label" /> C, F: exposed (good) E: not exposed (bad)
  • <img src="#" role="none" alt="none+alt" /> C, E, F: not exposed (technically good and following specs, but arguably not so good)
  • <img src="#" role="none" tabindex="0" /> C, E, F: exposed (good)
  • <img src="#" alt="" tabindex="0" /> C: exposed (good, but that is a gray area of the specs which do not specify what to do, notably in that case the implicit role is none…) E: not exposed F: exposed but given that alt="" is ignored, it doesn't mean much
  • <img src="#" role="none" aria-label="none+label+aria-hidden" aria-hidden="true"/> C, E, F: not exposed (bad? because global aria-*)
  • <img src="#" aria-hidden="true" aria-label="aria-hidden+label" /> C, E, F: not exposed (bad? because global aria-*)
  • <img src="#" aria-hidden="true" alt="aria-hidden+alt" /> C, E, F: not exposed (technically good)
  • <img src="#" aria-hidden="true" tabindex="0" /> C: exposed (good? because focusable) E, F: not exposed (bad?)

Conclusions

Rule for Chrome seems to be: focusable ? expose : aria-hidden ? hide : global aria-* ? expose : role

Rule for Edge seems to be: aria-hidden ? hide : focusable ? expose : role (ignoring the global aria-* exception)

Rule for Firefox seems to be: aria-hidden ? hide : focusable || global aria-* ? expose : role

  • Edge ignores the global aria-*. And keep a role of none instead of defaulting to implicit role when element is focusable.
  • The aria-hidden/focusable conflict is not specified, Chrome solves it in favour of the focusable and Edge/Firefox in favour of the aria-hidden.
  • The aria-hidden/other global aria-* conflict is not specified and everybody solves it in favour of aria-hidden.

On top of that, NVDA is hidding the stuff with either aria-hidden (that were exposed by Chrome). And it is not recomputing role further, so that for example the heading with an incorrect role of none in Edge is not listed in the list of headings in NVDA.

⚠️ **GitHub.com Fallback** ⚠️