dequelabs / axe-core

Accessibility engine for automated Web UI testing
https://www.deque.com/axe/
Mozilla Public License 2.0
5.75k stars 746 forks source link

`<slot>` with `display: inline-block` causes color-contrast to be incomplete #4468

Open frehner opened 1 month ago

frehner commented 1 month ago

Product

axe-core via @axe-core/playwright

Product Version

No response

Latest Version

Issue Description

Expectation

Adding display: inline-block styling to a <slot> element should not cause the color-contrast rule to be incomplete.

Actual

The color-contrast rule is incomplete with the warning:

Element's background color could not be determined because it is overlapped by another element

How to Reproduce

If you update axe-test-fixtures/fixtures/shadow-dom.html to include this new code:

<span id="shadow-root-3">Slotted</span>

<script>
      const shadowRoot3 = document
        .querySelector('#shadow-root-3')
        .attachShadow({ mode: 'open' });
      shadowRoot3.innerHTML = `
        <button id="shadow-button-3"><slot style="display:inline-block;"/></button>
      `;
</script>

and add this line to your axe-playwright.spec.ts "with include shadow DOM" test

        .include([['#shadow-root-3', '#shadow-button-3']])

And add an assertion for that new element. The test will fail, and you'll find the color-contrast rule will now be in results.incomplete.

Additional context

I'm fairly new to this repo, so I suspect that the issue may be in axe-core but I'm not sure. Let me know if that's the case and that I need to move it there. 👍

Zidious commented 1 month ago

Hey @frehner,

Thanks for reporting this issue. We'll investigate and circle back shortly!

dbjorge commented 1 month ago

Thanks for the issue @frehner! Your intuition was correct, this is an axe-core issue and not an axe-core-npm issue; I've transferred it accordingly.

This is happening because axe-core doesn't fully include slots with overridden display styles in its flattened tree - it skips over them and considered the slotted text to be a direct child of the button in this case, but then when it goes to identify "what is the stack of elements at the button's center point", that operation gives back a stack that does include the slot. So color-contrast gives up and says "oops, there's some element on top of the button (the slot), so I guess I have to incomplete the button".

Omitting styled slot elements like this from axe's flattened tree was originally an intentional decision, not an accidental omission (see commit d489c43 within the original shadow DOM implementation PR). The original motivation for omitting it was that Chrome 59 had "broken" support for it. I'm not sure whether there are still any issues with it browser support today, but I note that re-enabling the intentionally-disabled behavior to support this case (removing the false from the conditional on get-flattened-tree.js#L147) does fix this specific repro in chrome stable.

Different recent issue with the same root cause: #4335