---
title: "Fix Focusable Elements Inside aria-hidden"
description: "Learn how to fix aria-hidden-focus issues in Lighthouse accessibility audits"
canonical_url: "https://unlighthouse.dev/learn-lighthouse/accessibility/aria-hidden-focus"
last_updated: "2025-01-18"
---

Keyboard users can focus elements that screen reader users can't perceive, creating a confusing mismatch in experience.

## What's Happening

When you apply `aria-hidden="true"` to an element, you're telling assistive technologies to ignore it completely. But if that element contains focusable items like links, buttons, or form fields, keyboard users can still tab into them. The screen reader goes silent while focus lands on an invisible element - users hear nothing and have no idea where they are on the page.

## Diagnose

1. Open Chrome DevTools (F12)
2. Go to **Elements** panel and find elements with `aria-hidden="true"`
3. Expand the element and look for:

  - Links (`<a href>`)
  - Buttons (`<button>`)
  - Form inputs (`<input>`, `<select>`, `<textarea>`)
  - Elements with `tabindex="0"` or positive tabindex
4. Alternatively, tab through your page and listen with a screen reader - silence during focus indicates this issue

## Fix

### 1. Add tabindex="-1" to Focusable Descendants

Remove elements from the tab order while keeping aria-hidden:

```html
<!-- Before: Focusable link inside aria-hidden -->
<div aria-hidden="true">
  <a href="/terms">Terms of Service</a>
</div>

<!-- After: Link removed from tab order -->
<div aria-hidden="true">
  <a href="/terms" tabindex="-1">Terms of Service</a>
</div>
```

### 2. Use the inert Attribute

The `inert` attribute removes both focus AND aria-hidden in one step:

```html
<!-- Modern approach: inert handles everything -->
<div inert>
  <button>This button cannot be focused or seen by AT</button>
  <a href="/link">This link is also inert</a>
</div>
```

All modern browsers support `inert`, making it the preferred solution for modal backgrounds, hidden menus, and off-screen content.

### 3. Restructure to Avoid the Conflict

Rethink your HTML structure to avoid the conflict:

```html
<!-- Before: Icon with focusable link hidden -->
<div aria-hidden="true">
  <svg>...</svg>
  <a href="/download">Download</a>
</div>

<!-- After: Only hide the decorative icon -->
<div>
  <svg aria-hidden="true">...</svg>
  <a href="/download">Download</a>
</div>
```

### 4. Manage Focus When Showing/Hiding Content

For dynamic content like modals:

```javascript
function openModal(modal) {
  modal.removeAttribute('aria-hidden')
  modal.removeAttribute('inert')
  modal.querySelector('button, [href], input').focus()
}

function closeModal(modal) {
  modal.setAttribute('inert', '')
  // or: modal.setAttribute('aria-hidden', 'true')
  // and add tabindex="-1" to all focusable children
}
```

## Framework Examples

<callout icon="i-logos-nuxt-icon">

In Vue/Nuxt, use a composable to manage inert state:

```html
<script setup>
const isMenuOpen = ref(false)
</script>

<template>
  <div :inert="!isMenuOpen || undefined">
    <nav>
      <a href="/about">About</a>
      <a href="/contact">Contact</a>
    </nav>
  </div>
</template>
```

Note: Bind to `undefined` (not `false`) to remove the attribute when not needed.

</callout>

## Verify the Fix

1. Re-run Lighthouse accessibility audit
2. Tab through the page with keyboard only - hidden elements must not be focusable
3. Test with a screen reader:

  - Tab navigation should skip all inert/hidden regions
  - No silent focus gaps should occur
4. Check DevTools Accessibility tree - hidden elements should not appear

## Common Mistakes

- **Only adding aria-hidden without managing focus**: Screen readers are fixed, but keyboard users still get stuck.
- **Using CSS display:none but also aria-hidden**: `display:none` already hides from both, making aria-hidden redundant.
- **Forgetting dynamically added content**: New buttons added via JavaScript inside aria-hidden regions are still focusable.
- **Not using inert for modals**: When a modal opens, the background content should use `inert` to prevent focus escape.

## When to use each approach

<table>
<thead>
  <tr>
    <th>
      Scenario
    </th>
    
    <th>
      Solution
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Modal backdrop/background
    </td>
    
    <td>
      <code>
        inert
      </code>
      
       on background
    </td>
  </tr>
  
  <tr>
    <td>
      Off-screen mobile menu
    </td>
    
    <td>
      <code>
        inert
      </code>
      
       when closed
    </td>
  </tr>
  
  <tr>
    <td>
      Decorative icons with nearby text
    </td>
    
    <td>
      <code>
        aria-hidden
      </code>
      
       on icon only
    </td>
  </tr>
  
  <tr>
    <td>
      Collapsed accordion content
    </td>
    
    <td>
      <code>
        inert
      </code>
      
       when collapsed
    </td>
  </tr>
  
  <tr>
    <td>
      Permanently hidden content
    </td>
    
    <td>
      <code>
        display: none
      </code>
      
       (no ARIA needed)
    </td>
  </tr>
</tbody>
</table>

## Related issues

ARIA focus issues often appear alongside:

- [Required ARIA attributes](/learn-lighthouse/accessibility/aria-required-attr) - Missing state attributes on interactive elements
- [Valid ARIA attributes](/learn-lighthouse/accessibility/aria-valid-attr) - Typos in attribute names cause silent failures
- [Tabindex](/learn-lighthouse/accessibility/tabindex) - Both affect keyboard navigation order

## Test your entire site

This issue commonly appears in modals, mobile navigation, and dynamically shown/hidden content across your site. Unlighthouse audits every page automatically, catching aria-hidden focus traps wherever they occur so keyboard and screen reader experiences stay in sync.
