auditmysitev2.0.2

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.

display_modes_described_text.htmlHTML
<!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.

display_modes_conforming.htmlHTML
<!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.