Visualisation text layer hidden from assistive technology
display/text-hidden
- WCAG success criterion
- 1.1.1 (level A)
- Outcome class
- Automatic. An automated check that can report a confirmed violation.
- Area
- Accessibility, Content & Alternatives
- Default severity
- high
- axe-core rule
display/text-hidden
Why we flag this
Screen reader users do not get the statement of the visualisation.
hidden, aria-hidden=true, inert or display:none/visibility:hidden on [data-viz-text] or an ancestor.
What the rule checks
Scope. Pages with figure[data-viz] and a [data-viz-text], in any mode.
Expectation. A best-practice violation at the text layer when it is removed from assistive technology while its figure is shown: hidden attribute, aria-hidden=true, inert, or CSS (display: none) on it or an ancestor, also when set by script after load. Visually hidden but exposed (clip pattern) passes. A figure that is itself not shown (inactive tab panel with hidden) hides its statement for everyone and passes. A CSS-hidden or hidden layer that a rendered element of the figure references by aria-describedby or aria-details still reaches assistive technology as a description: a low review, not a violation; inert does not get that exception.
Source. BarrierLab display-mode convention draft v0 (barrierlab/plan/03), anchored to WCAG 2.2 SC 1.1.1; accname 1.2 (description from hidden referenced nodes); HTML inert
Detection: page; needs dom, computed_style, geometry.
Failing example
The check reports a violation here. Corpus case display_modes_described_text, element div#pressure-text. The page may contain further findings for other rules.
<!DOCTYPE html>
<!-- Display-mode convention (#653), rendered in visual mode (#704). Figure f1
hides its text layer with display:none outside text mode, but the chart
and the figure's stage reference it by aria-describedby: accname 1.2
computes the description from the hidden node, so the statement still
reaches assistive technology. Expect a low review note, no violation.
Figure f2 hides its text layer the same way without any reference:
that stays a display/text-hidden violation. -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Display modes: text layer delivered as description</title>
<script>document.documentElement.dataset.display = 'visual';</script>
<style>
html:not([data-display="text"]) [data-viz-text] { display: none; }
html[data-display="text"] [data-viz-static] { display: none; }
</style>
</head>
<body>
<header>
<nav aria-label="Display">
<label for="display-toggle">Display</label>
<select id="display-toggle" data-display-toggle>
<option value="visual" selected>Visual</option>
<option value="calm">Calm</option>
<option value="text">Text</option>
</select>
</nav>
</header>
<main>
<h1>Atmosphere layers</h1>
<figure id="f1" data-viz="diagram">
<div data-viz-static>
<svg role="img" aria-label="Layers of the atmosphere" aria-describedby="layers-desc"
width="300" height="120" viewBox="0 0 300 120">
<rect width="300" height="60" fill="#4575b4"></rect>
<rect y="60" width="300" height="60" fill="#91bfdb"></rect>
</svg>
<div role="application" aria-label="Layer explorer" aria-describedby="layers-desc"
tabindex="0" style="width: 300px; height: 40px;">Explore</div>
</div>
<div id="layers-desc" data-viz-text>
<p>The troposphere reaches about 12 km, the stratosphere about 50 km.</p>
</div>
<figcaption>Layers of the atmosphere</figcaption>
</figure>
<figure id="f2" data-viz="chart">
<div data-viz-static>
<svg role="img" aria-label="Pressure by altitude" width="300" height="120" viewBox="0 0 300 120">
<rect width="300" height="120" fill="#d73027"></rect>
</svg>
</div>
<div id="pressure-text" data-viz-text>
<p>Air pressure halves about every 5.5 km of altitude.</p>
</div>
<figcaption>Pressure by altitude</figcaption>
</figure>
</main>
</body>
</html>Passing example
The check passes here and reports nothing. Corpus case display_modes_conforming. The page may contain further findings for other rules.
<!DOCTYPE html>
<!-- Display-mode convention (#653) followed correctly, rendered in text mode:
data-display is set by a blocking script in <head>, the toggle exists,
the visualisation's media is hidden in text mode and its text layer is
visible. Expect no display/* finding. -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Display modes: conforming page</title>
<script>document.documentElement.dataset.display = 'text';</script>
<style>
html[data-display="text"] [data-viz-static],
html[data-display="text"] [data-viz-live] { display: none; }
html:not([data-display="text"]) [data-viz-text] {
position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
}
</style>
</head>
<body>
<header>
<nav aria-label="Display">
<label for="display-toggle">Display</label>
<select id="display-toggle" data-display-toggle>
<option value="visual">Visual</option>
<option value="calm">Calm</option>
<option value="text" selected>Text</option>
</select>
</nav>
</header>
<main>
<h1>Temperature since 1850</h1>
<figure id="f1" data-viz="chart">
<div data-viz-static>
<svg role="img" aria-label="Warming stripes" width="300" height="120" viewBox="0 0 300 120">
<rect width="150" height="120" fill="#4575b4"></rect>
<rect x="150" width="150" height="120" fill="#d73027"></rect>
</svg>
</div>
<div data-viz-text>
<p>The global mean surface temperature rose by about 1.3 degrees since 1850.</p>
<table>
<caption>Temperature anomaly</caption>
<tr><th scope="col">Year</th><th scope="col">Anomaly</th></tr>
<tr><td>1850</td><td>0.0</td></tr>
<tr><td>2025</td><td>1.3</td></tr>
</table>
<p>Source: example data.</p>
</div>
<figcaption>Global temperature anomaly</figcaption>
</figure>
</main>
</body>
</html>This page is generated from the rule catalogue and the rule contracts; see therule overview for how the outcome classes are derived.