ARIA attributes don’t always work in Shadow DOM

Bobby Bailey

Bobby Bailey

Jump to Article

Vibe Check – Why aria-describedby and other ARIA attributes don’t always work in Shadow DOM

ARIA (Accessible Rich Internet Applications) attributes are powerful tools for improving accessibility, but they have limitations—especially when used inside the Shadow DOM. Many designers and developers assume that aria-labelledby and aria-describedby will work seamlessly across Shadow DOM boundaries, only to discover that assistive technologies can’t access referenced elements outside their Shadow Roots.

Not all ARIA attributes fail in the Shadow DOM, but those that rely on referencing elements outside the Shadow Root often break. Let’s explore why this happens and how to fix it.

A personal story – When ARIA failed inside the Shadow DOM

I once worked on a project that relied heavily on custom web components. We designed accessible modals, tooltips, and input fields—all following best practices. Everything had clear labels, descriptions, and appropriate aria-describedby references.

But when we tested with a screen reader, the descriptions weren’t being announced. Forms inside the Shadow DOM had error messages, but screen readers ignored them. Tooltips linked with aria-describedby didn’t work either.

After hours of debugging, we found the issue: ARIA attributes don’t always pierce the Shadow DOM. If a label or description is outside the Shadow Root, assistive technology won’t recognize it. That realization changed how we approached accessibility for web components.

Elevate the vibe – Why ARIA attributes don’t work across Shadow DOM boundaries

1) Shadow DOM creates an isolated accessibility tree

The problem:

The Shadow DOM forms its own separate accessibility tree, meaning elements inside it cannot reference elements outside of it using ARIA attributes.

If aria-labelledby or aria-describedby points to an ID outside the Shadow DOM, assistive technologies ignore it.

What happens?

<input aria-describedby="error-message"> will work only if #error-message is inside the same Shadow Root.

If #error-message exists in the Light DOM, the screen reader won’t make the connection.

Fix it:

Place all referenced labels and descriptions inside the same Shadow Root as the element they describe.

If external references are needed, use alternative methods like slotting content into the Shadow DOM.

2) Some ARIA attributes still work in Shadow DOM

Not all ARIA fails in Shadow DOM! Attributes that apply to the element itself still function correctly.

What works:

role attributes (e.g., role="button", role="dialog").

ARIA states (aria-disabled, aria-expanded, aria-checked).

aria-live (as long as the live region is inside the same Shadow Root).

What doesn’t work across Shadow DOM boundaries:

aria-labelledby and aria-describedby (if referencing an external element).

aria-controls (if controlling an element outside the Shadow DOM).

aria-activedescendant (if pointing to an element outside the Shadow DOM).

3) Tooltips and error messages may not be announced

The problem:

Many custom components rely on tooltips or inline error messages that use aria-describedby.

If these messages exist outside the Shadow DOM, assistive technologies won’t associate them correctly.

Fix it:

Keep error messages inside the Shadow Root with the input field.

If external text is required, consider dynamically cloning or slotting it into the Shadow DOM.

4) Focus management and ARIA live regions may break

The problem:

aria-live elements outside the Shadow DOM won’t notify screen readers about updates inside it.

Focus may shift unpredictably when navigating between Light DOM and Shadow DOM components.

Fix it:

Use Shadow DOM-friendly focus management with tabindex and manual event handling.

Place aria-live elements inside the Shadow DOM so they announce changes correctly.

Vibe boost – How to make Shadow DOM components accessible

1) Keep ARIA references inside the same Shadow Root

Instead of referencing an external ID, ensure labels and descriptions exist inside the same component.

Example of broken ARIA:

<custom-input aria-describedby="error-message"></custom-input>
<span id="error-message">Invalid input</span> <!-- Won't be recognized inside Shadow DOM -->

Example of fixed ARIA:

<custom-input>
 <span slot="error" id="error-message">Invalid input</span>
</custom-input>

2) Use slot elements to expose necessary content

If descriptions or labels exist in the Light DOM, slot them inside the Shadow DOM.

Example:

<custom-button>
 <span slot="label">Submit</span>
</custom-button>

3) Provide explicit labeling within components

Avoid relying on external IDs for aria-labelledby and aria-describedby.

Use <label> elements inside the Shadow Root.

4) Test with assistive technology

Verify components with screen readers (NVDA, JAWS, VoiceOver).

Check keyboard focus order to ensure navigation is smooth.

Ensure error messages and descriptions are properly announced.

Self-reflection – Evaluating your use of ARIA in Shadow DOM

Ask yourself:

Are aria-labelledby and aria-describedby referencing elements inside the same Shadow Root?

Have I tested my web components with a screen reader?

Do my tooltips, error messages, and labels work without external dependencies?

Am I using slots to expose necessary content to assistive technology?

If any of these raise concerns, it’s time to rethink your ARIA implementation!

Vibe in action – Making ARIA work with Shadow DOM

1) Apply what you’ve learned

Audit components to remove broken ARIA references.

Ensure that error messages and labels are contained within the Shadow DOM.

2) Share the knowledge

Educate teams about ARIA limitations inside Shadow DOM.

Advocate for designing accessible components from the start.

3) Keep learning

Follow WCAG guidelines and best practices for ARIA in Shadow DOM.

Stay updated on browser improvements for web component accessibility.

Vibing out

ARIA is an essential tool for web accessibility, but it doesn’t automatically work across Shadow DOM boundaries. Understanding these limitations helps designers and developers build truly inclusive experiences.

By keeping ARIA attributes inside the Shadow Root, using slots for necessary content, and testing with assistive technology, we can ensure that web components remain functional, usable, and accessible to all.

Because when accessibility is built into the foundation, everyone benefits.

Support my work in accessibility

Creating accessible content takes time, care, and deep testing — and I love every minute of it. From writing blog posts to doing live audits and building checklists, everything I create is designed to make the digital world more inclusive.If something here helped you — whether it saved you time, taught you something new, or gave you insight into accessibility — consider supporting my work.

You can buy me a coffee to help keep this platform going strong:

Buy Me a Coffee

Every coffee goes toward:

  • Creating new articles with accessibility tips, tools, and testing methods
  • Covering hosting, software, and assistive tech costs
  • Supporting free education for designers, developers, and testers
  • Making a meaningful difference for people living with disabilities

Thanks for being part of this mission to build a more accessible web — one page at a time.