auditmysitev2.0.2

Visualisation text layer missing in text mode

display/text-not-visible

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-not-visible

Why we flag this

In text mode the statement of the visualisation is lost.

[data-viz-text] missing, empty or not visible with html[data-display=text].

What the rule checks

Scope. Pages rendered in text mode with figure[data-viz] whose [data-viz-text] has content.

Expectation. A best-practice violation at the figure when, in text mode, none of its non-empty text layers is rendered: still clipped to 1 x 1 by the visually-hidden pattern, or transparent (opacity 0). A text layer removed from assistive technology is display/text-hidden instead and not reported twice; a figure without any text is viz/text-missing. Outside text mode the rule does not apply.

Source. BarrierLab display-mode convention draft v0 (barrierlab/plan/03), anchored to WCAG 2.2 SC 1.1.1; best practice

Detection: page; needs dom, computed_style, geometry.

Failing example

The check reports a violation here. Corpus case visual_display_text_mode_broken, element figure#f1. The page may contain further findings for other rules.

visual_display_text_mode_broken.htmlHTML
<!DOCTYPE html>
<!-- Display-mode convention (#653), rendered in text mode, with the text-mode
     mistakes real pages make: a text layer that stays visually hidden (clip
     pattern) or transparent in text mode, and still images that are not
     hidden. A 32x32 icon is allowed, 33x33 is not. -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Display modes: text mode that keeps pictures and hides text</title>
<script>document.documentElement.dataset.display = 'text';</script>
<style>
  body { color: #111111; background: #ffffff; }
  /* Forgot to reveal the text layer in text mode. */
  #t1 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  #t5 { opacity: 0; }
  html[data-display="text"] #s1, html[data-display="text"] #s5 { display: none; }
</style>
</head>
<body>
<header>
  <a href="#main" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Skip to main content</a>
  <label for="display-toggle">Display</label>
  <select id="display-toggle" data-display-toggle style="min-width: 44px; min-height: 44px">
    <option value="visual">Visual</option>
    <option value="calm">Calm</option>
    <option value="text" selected>Text</option>
  </select>
  <nav aria-label="Main"><a href="#main" aria-current="page" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Overview</a></nav>
</header>
<main id="main">
  <h1>River levels</h1>
  <figure id="f1" data-viz="diagram">
    <div id="s1" data-viz-static><svg width="300" height="120" aria-hidden="true"><rect width="300" height="120" fill="#4575b4"></rect></svg></div>
    <div id="t1" data-viz-text><p>The river rose by 80 centimetres overnight.</p></div>
    <figcaption>River level at the old bridge</figcaption>
  </figure>
  <figure id="f2" data-viz="diagram">
    <img id="s2" data-viz-static width="300" height="120" alt="Bar diagram of rainfall"
      src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='120'%3E%3Crect width='300' height='120' fill='%23336699'/%3E%3C/svg%3E">
    <div id="t2" data-viz-text><p>Rainfall was twice the monthly average.</p></div>
    <figcaption>Rainfall in October</figcaption>
  </figure>
  <figure id="f3" data-viz="diagram">
    <svg id="icon3" width="32" height="32" aria-hidden="true"><circle cx="16" cy="16" r="14" fill="#d73027"></circle></svg>
    <div id="t3" data-viz-text><p>Flood warning level 2 is in force.</p></div>
    <figcaption>Warning level</figcaption>
  </figure>
  <figure id="f4" data-viz="diagram">
    <svg id="icon4" width="33" height="33" aria-hidden="true"><circle cx="16" cy="16" r="14" fill="#d73027"></circle></svg>
    <div id="t4" data-viz-text><p>The ferry is suspended until further notice.</p></div>
    <figcaption>Ferry status</figcaption>
  </figure>
  <figure id="f5" data-viz="diagram">
    <div id="s5" data-viz-static><svg width="300" height="120" aria-hidden="true"><rect width="300" height="120" fill="#91bfdb"></rect></svg></div>
    <div id="t5" data-viz-text><p>The water temperature is 11 degrees.</p></div>
    <figcaption>Water temperature</figcaption>
  </figure>
</main>
<footer><p>Footer text</p></footer>
</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.