aria-hidden
Indicates whether the element is exposed to an accessibility API. Used to hide content from assistive technologies while keeping it visually present.
Overview
The aria-hidden attribute indicates whether an element is exposed to the accessibility API. When set to true, the element and all its descendants are hidden from assistive technologies like screen readers.
This attribute is particularly useful for hiding decorative content, redundant text, or off-screen content that shouldn't be announced to screen reader users. However, it must be used carefully to avoid hiding important information.
Critical Warning
Adding aria-hidden="true" to an element does NOT prevent focus. If the hidden element contains focusable children, keyboard users can still focus them, which creates a confusing experience. Use the inert attribute instead when you need to hide and disable interaction.
Live Demo: aria-hidden in Action
Toggle aria-hidden to see how it affects screen reader announcements:
Icon Button Example
Icon has aria-hidden="true"
Decorative Element
Emoji has aria-hidden="true"
Screen reader behavior: When aria-hidden="true", screen readers skip the icon/emoji entirely. When false or removed, screen readers may announce "checkmark icon" or "artist palette" which can be redundant with the visible text.
Attribute Values
trueThe element and all of its descendants are hidden from the accessibility API. Screen readers will completely ignore this content.
falseExplicitly exposes the element to the accessibility API. Typically used to override an inherited aria-hidden="true" from an ancestor.
undefined (no attribute)When the attribute is not present, the element's visibility to assistive technology is determined by its natural state in the DOM and CSS visibility.
Code Examples
Basic Usage - Decorative Icons
<!-- Hiding decorative content from screen readers -->
<button>
<svg aria-hidden="true" focusable="false">
<!-- decorative icon -->
</svg>
Save Document
</button>
<!-- Icon-only button with accessible label -->
<button aria-label="Close">
<svg aria-hidden="true" focusable="false">
<!-- X icon -->
</svg>
</button>Modal Background Hiding
<!-- Hiding background content when modal is open -->
<div id="main-content" aria-hidden="true">
<!-- Page content hidden from assistive tech when modal is open -->
<header>...</header>
<main>...</main>
<footer>...</footer>
</div>
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h2 id="modal-title">Confirm Action</h2>
<p>Are you sure you want to proceed?</p>
<button>Yes</button>
<button>No</button>
</div>Decorative Images
<!-- Hiding purely decorative images -->
<div class="hero-section">
<img
src="/decorative-background.jpg"
alt=""
aria-hidden="true"
/>
<h1>Welcome to Our Site</h1>
</div>
<!-- Hiding duplicate content -->
<nav aria-label="Main navigation">
<a href="/">
<img src="/logo.png" alt="" aria-hidden="true" />
<span>Company Name</span>
</a>
</nav>Common Mistakes to Avoid
<!-- ⚠️ WRONG: Don't hide focusable elements -->
<div aria-hidden="true">
<!-- This button can still receive focus! -->
<button>Click me</button>
</div>
<!-- ✅ CORRECT: Use inert attribute instead -->
<div inert>
<button>This is properly hidden and unfocusable</button>
</div>
<!-- ⚠️ WRONG: Don't hide content users need -->
<form>
<label for="email">Email</label>
<input id="email" type="email" />
<!-- Error message should NOT be hidden! -->
<span aria-hidden="true">Invalid email format</span>
</form>
<!-- ✅ CORRECT: Error messages should be announced -->
<form>
<label for="email">Email</label>
<input id="email" type="email" aria-describedby="error" />
<span id="error" role="alert">Invalid email format</span>
</form>React Examples
// React Component Examples
import { useState, useEffect, useRef } from 'react';
// Decorative Icon Button
function IconButton({ icon, label, onClick }) {
return (
<button onClick={onClick} aria-label={label}>
<span aria-hidden="true">{icon}</span>
</button>
);
}
// Modal with Background Hiding
function Modal({ isOpen, onClose, title, children }) {
const mainRef = useRef(null);
useEffect(() => {
const mainContent = document.getElementById('main-content');
if (mainContent) {
mainContent.setAttribute('aria-hidden', isOpen ? 'true' : 'false');
}
return () => {
if (mainContent) {
mainContent.removeAttribute('aria-hidden');
}
};
}, [isOpen]);
if (!isOpen) return null;
return (
<div
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
<h2 id="modal-title">{title}</h2>
{children}
<button onClick={onClose}>Close</button>
</div>
);
}
// Loading Spinner (decorative)
function LoadingButton({ isLoading, children, ...props }) {
return (
<button disabled={isLoading} {...props}>
{isLoading && (
<svg
aria-hidden="true"
className="spinner"
focusable="false"
>
{/* spinner SVG */}
</svg>
)}
<span className={isLoading ? 'sr-only' : ''}>
{isLoading ? 'Loading...' : children}
</span>
</button>
);
}Best Practices
Use aria-hidden="true" for purely decorative icons that accompany visible text labels
Hide duplicate or redundant information that would be confusing if announced twice
Use on modal backgrounds to prevent screen readers from accessing underlying content
Add focusable="false" to SVGs along with aria-hidden="true" for better cross-browser support
Consider using the inert attribute when you need to hide AND disable interaction
Never hide content that users need to understand the interface
Don't use aria-hidden on focusable elements - users can still tab to them
Don't hide form labels, error messages, or important status information
Avoid using aria-hidden to hide content that should just be visually hidden (use CSS instead)
Don't set aria-hidden="false" unless overriding an inherited aria-hidden="true"
Common Use Cases
aria-hidden vs CSS Display/Visibility
aria-hidden="true"
- • Hidden from screen readers only
- • Still visible on screen
- • Still in tab order if focusable
- • Still takes up space
display: none
- • Hidden from everyone
- • Not visible on screen
- • Removed from tab order
- • Takes no space
visibility: hidden
- • Hidden from everyone
- • Not visible on screen
- • Removed from tab order
- • Still takes up space
Accessibility Notes
Inheritance Behavior
When you set aria-hidden="true" on an element, all descendants are also hidden from the accessibility tree. You cannot expose a descendant with aria-hidden="false" if an ancestor has aria-hidden="true" in most browsers.
Focus Trap Warning
aria-hidden does NOT prevent keyboard focus. If a user tabs to a focusable element inside an aria-hidden container, screen readers may announce nothing or something confusing. Use the inert attribute or manage focus programmatically to prevent this.
Browser Support
aria-hidden is well-supported across all modern browsers and screen readers. However, behavior with focus can vary. Always test with actual assistive technology to ensure the expected experience.

