Using CSS to hide elements visually while keeping them in the HTML source doesn't actually make them accessible to screen readers—often it does the opposite. Screen readers read every element in the source code unless explicitly marked as decorative, so hiding content visually while leaving it in the code creates confusion and noise for blind users.
A common web development pattern hides content visually using CSS (display: none, visibility: hidden, or opacity: 0) for layout purposes. For sighted users, this works perfectly—the content disappears from the visual layout. However, screen reader users and assistive technology encounter a critical problem: many CSS-based hiding methods simultaneously hide content from accessibility APIs, making it inaccessible.
Visual hiding removes content from the rendered page layout. Accessibility hiding removes content from the accessibility tree—the structured representation of page content that screen readers consume. These are not equivalent operations, yet many developers treat them as interchangeable.
display: none removes an element from both the visual layout AND the accessibility tree. Screen reader users cannot access this content at all. visibility: hidden similarly hides from both visual rendering and accessibility. opacity: 0 (making content transparent) hides visually but does not affect the accessibility tree—screen readers still see it, which is sometimes desirable and sometimes problematic.
The accessibility tree is the document structure that assistive technologies navigate. When an element is removed from the accessibility tree, a screen reader user cannot find it, regardless of whether it's technically present in the HTML source code. This creates a hidden digital divide: disabled users see different content than sighted users without knowing what they're missing.
display: none removes it from the accessibility tree entirely, defeating its purpose. The link should use position: absolute with off-screen positioning that keeps it accessible.display: none on a decorative sidebar visible to sighted users. However, if this "decorative" element contains meaningful secondary information, screen reader users never find it.display: none. If those columns contain essential information for mobile-size screens, hiding them from the accessibility tree creates content loss for disabled mobile users.display: none. A screen reader user navigating via keyboard might never discover the hidden tab content because it's removed from the accessibility tree.Screen reader software (NVDA, JAWS, VoiceOver) reads the accessibility tree, not the HTML source. When you hide content with display: none, the browser's accessibility layer removes that node from the tree. The screen reader has no awareness the content exists. For a blind user, this content is as if it was deleted from the server.
Some developers argue that if content is visually hidden, it should be accessibility-hidden too—otherwise, it creates redundancy or confusion for screen reader users. This is a valid point in certain contexts. However, the solution is not to hide content inaccessibly; it's to provide proper ARIA attributes that signal to assistive technology that content is hidden and explain why.
aria-hidden="true" on the element and its children. This explicitly tells assistive technology to skip this content. Unlike display: none, aria-hidden communicates intentionality—the developer has thought about accessibility.position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden;. This positions content off-screen, visually hiding it but keeping it in the accessibility tree. Screen reader users can access it; sighted users cannot.display: none. Instead, use aria-expanded="false" and aria-hidden="true" together, combined with CSS max-height: 0; overflow: hidden; for animation. This signals that content is intentionally hidden but can be revealed.You can identify these failures manually by navigating with Tab key (keyboard navigation) and noting if you can access all interactive elements and content. More reliably, use a free screen reader like NVDA and enable screen reader mode; navigate the page and see if you encounter content that appears visually but is inaccessible. AI accessibility checkers like Copilot Designer's analyzer can flag inappropriate use of display: none on potentially meaningful content and missing aria-hidden on decorative elements.
Try this: Inspect a website you use regularly. Look for any element with display: none in its CSS (right-click → Inspect Element, look at the Styles panel). Then check if this element has aria-hidden="true" defined. If it's hidden with display: none but lacks aria-hidden, it's an accessibility failure. Document these findings—they're common issues that developers may not realize exist.
Peri can explain this concept, give practical examples, help you decide whether it applies to your situation, or recommend a journey if appropriate.
Explore related journeys or tell Peri what you're working through.