How to hide from screen readers
Screen readers are how a lot of people browse the web—converting text to speech or braille for folks who can't see the screen. But here's the thing: sometimes you gotta hide stuff from them. Not to be shady, but for legit reasons. Like decorative icons that don't mean anything, or text that'd just confuse someone if read aloud. Or off-screen elements that make no sense when announced. It's all about making the experience better for everyone, not excluding people. This article walks through the right and wrong ways to manage screen reader visibility using HTML, CSS, and ARIA attributes.
Why would you need to hide content from screen readers?
Look, hiding stuff from screen readers isn't about making your site less accessible. It's about improving clarity and reducing auditory clutter. Think about it—a decorative icon that's just there for visual flair? Nobody needs that announced. Or a "read more" link next to every single product in a list—that'd get real annoying real fast. You're better off with one clear label. When you hide the redundant or purely visual stuff, screen reader users can actually navigate without all that noise.
What is the correct way to hide an element from screen readers?
The gold standard here is aria-hidden="true". This attribute tells assistive tech to just ignore the element and everything inside it. Simple to use, works across all modern browsers and screen readers. No fuss.
Example:<span aria-hidden="true">★</span>- That star icon? Screen readers won't even know it exists.Now, if you want something hidden visually but still announced—like a skip-link or a label that's only for screen readers—you need a CSS class that clips it visually but keeps it in the accessibility tree.
What is the CSS class for visually hiding an element while keeping it accessible to screen readers?
This is the "screen-reader-only" or "visually hidden" pattern. The trick is using a combo of CSS properties that yank the element from the visual layout without booting it from the DOM or the accessibility tree.
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }This is the go-to for text that only screen readers should see—like extra context for an image, or a heading that's just for navigation purposes.
What are the common mistakes when hiding content from screen readers?
People mess this up all the time. Here's what to avoid:
- Using
display: noneorvisibility: hidden: These nuke the element from both visual AND accessibility tree. Only use these when you genuinely want nobody to see or hear it.- Using
width: 0; height: 0;orfont-size: 0;: Unreliable as hell. Some screen readers might still pick them up, and they can mess with your layout.- Using
aria-hidden="true"on focusable elements: This is a big no-no. If you hide a button or link this way, users can still tab to it but hear nothing. Total ghost element situation.- Nesting
aria-hiddenincorrectly: If a parent hasaria-hidden="true", all children are hidden—even if you try to set a child toaria-hidden="false". The parent always wins.How does the ARIA attribute
role="presentation"orrole="none"affect screen readers?These roles strip the semantic meaning from an element. So a
<button>withrole="presentation"won't be announced as a button anymore. But the text inside it? Still gets read. Handy for removing meaning from a decorative element that still has text, but it doesn't hide the thing entirely. For full-on hiding, stick witharia-hidden="true".Data table: Comparison of hiding methods
Method Visually Hidden? Screen Reader Hidden? Best Use Case aria-hidden="true"No Yes Decorative icons, redundant text .sr-onlyCSS classYes No Labels, skip links, extra context display: noneYes Yes Content that should be completely removed (e.g., mobile-only elements on desktop) role="presentation"No No (removes semantics only) Removing semantic meaning from a layout element Checklist for hiding content from screen readers
- Figure out the purpose: Is this decorative or functional?
- For decorative stuff: Slap
aria-hidden="true"on the container.- For functional content that should be visually hidden: Use the
.sr-onlyCSS class.- Never hide focusable elements with
aria-hidden.- Test with an actual screen reader (NVDA, VoiceOver, whatever you've got).
- Make sure hidden content doesn't contain anything critical.
Frequently Asked Questions (FAQ)
Can I use
aria-hidden="true"on a parent element to hide its children?Yeah, absolutely. When you put
aria-hidden="true"on a parent, all its descendants get hidden from the accessibility tree too. Common pattern for hiding entire sections—like a decorative carousel or a set of social media icons that are already labeled elsewhere.Does
aria-hidden="true"affect keyboard navigation?Nope. The element stays in the tab order. So if you hide a focusable element, users can still tab to it—but the screen reader won't say a word. That's a terrible experience. Always make sure focusable elements are either visible or have a valid accessible name.
Is it better to use
aria-labeloraria-hiddenfor icons?Depends. For decorative icons that don't convey any info (like a purely visual star rating background), use
aria-hidden="true". For informative icons (like a telephone icon representing a phone number), usearia-labelon the link or button to provide a text alternative, and hide the icon itself.What is the difference between
hiddenattribute andaria-hidden?Good question. The HTML
hiddenattribute is a global one that hides an element from every user—visually and from screen readers. It's basicallydisplay: none. Thearia-hiddenattribute only hides the element from assistive technology, not from the visual display. Usehiddenwhen you want nobody to see or hear it.Short Summary
- Primary method for hiding from screen readers: Use the
aria-hidden="true"attribute on decorative or redundant elements.- Visually hiding while keeping accessible: Apply the
.sr-onlyCSS class to hide content visually but keep it readable by screen readers.- Avoid common pitfalls: Never use
display: noneorvisibility: hiddenfor content that should only be hidden from screen readers, and never hide focusable elements.- Test thoroughly: Always validate your implementation with real screen reader software and keyboard navigation to ensure a seamless experience for all users.