Accessibility pattern · Disclosure and content

Glossary term

Each term is a button that opens a short definition beside it; the definition is announced from a live region and Escape closes it. Every definition lives once, in a glossary list below, and the toggletip copies its words from there, with a link to the full entry and a link back.

WCAG criteria
7
Keyboard rules
4
Checked with
axe, keyboard and the inspector

Live demo

Try it

Use it with a mouse, a keyboard or a screen reader. The inspector beside it shows what the browser tells assistive technology as you go: focus, state changes and announcements.

Choosing text colors

compares how light the text is with how light its background is. asks for at least 4.5:1 for body text; can pass at 3:1. Both figures are worked out from each color's , not from its hue.

Glossary

Contrast ratio

How much lighter one color is than another, from 1:1 for no difference to 21:1 for black on white.

It is worked out from the relative luminance of the two colors as (L1 + 0.05) / (L2 + 0.05), where L1 is the lighter one.

Back to text
WCAG

Web Content Accessibility Guidelines: the W3C standard that many accessibility laws refer to.

Version 2.2 became a W3C Recommendation in October 2023. Its success criteria are graded A, AA and AAA.

Back to text
Large text

Text of at least 18 points, or 14 points in bold: about 24 and 18.66 CSS pixels.

Bigger letters stay readable at lower contrast, so large text needs 3:1 rather than 4.5:1.

Back to text
Relative luminance

How bright a color is, from 0 for black to 1 for white, weighted for how the eye sees red, green and blue.

Green counts for most of it and blue for least, which is why yellow text on white fails and pure blue on white passes.

Back to text

The demo works without JavaScript only as far as its HTML does; the inspector needs JavaScript.

Keyboard

Keys it answers to

Every action works without a pointer.

KeyWhat it does
TabMoves through the terms in the text; from an open definition's term, the next Tab reaches its See the full entry link.
Enter or SpaceOn a term, opens its short definition, or closes it if it is open. Opening one closes any other.
EscapeCloses the open definition and puts focus back on its term.
EnterOn See the full entry, goes to the term in the glossary and moves focus there; on Back to text, returns to the term in the paragraph.

Screen readers

What it announces

Written from the roles, names and states in the markup.

WhenExpected announcement
Focus reaches a termContrast ratio, button, collapsed
Enter opens itExpanded. Contrast ratio. How much lighter one color is than another, from 1:1 for no difference to 21:1 for black on white. See the full entry
See the full entry is followedContrast ratio, term
Focus reaches Back to textBack to text, link, Contrast ratio

These are expected announcements, not recordings. Wording and order differ between screen readers and browsers.

Code

Copy the code

The exact files this demo runs on. The styles are served with a prefix that keeps this site's own styles out of the demo; what you copy is the original.

The markup

<div class="ap-glossary-term" data-ap-glossary-term>
  <h3 class="ap-glossary-term__name">Choosing text colors</h3>
  <p class="ap-glossary-term__text"><span class="ap-glossary-term__wrap"><button type="button" class="ap-glossary-term__term" id="gt-ref-contrast" aria-expanded="false" data-ap-term="gt-contrast">Contrast ratio</button><span class="ap-glossary-term__tip" role="status"></span></span> compares how light the text is with how light its background is. <span class="ap-glossary-term__wrap"><button type="button" class="ap-glossary-term__term" id="gt-ref-wcag" aria-expanded="false" data-ap-term="gt-wcag"><abbr>WCAG</abbr></button><span class="ap-glossary-term__tip" role="status"></span></span> asks for at least 4.5:1 for body text; <span class="ap-glossary-term__wrap"><button type="button" class="ap-glossary-term__term" id="gt-ref-large" aria-expanded="false" data-ap-term="gt-large">large text</button><span class="ap-glossary-term__tip" role="status"></span></span> can pass at 3:1. Both figures are worked out from each color's <span class="ap-glossary-term__wrap"><button type="button" class="ap-glossary-term__term" id="gt-ref-luminance" aria-expanded="false" data-ap-term="gt-luminance">relative luminance</button><span class="ap-glossary-term__tip" role="status"></span></span>, not from its hue.</p>

  <div class="ap-glossary-term__glossary">
    <h4 class="ap-glossary-term__label">Glossary</h4>
    <dl class="ap-glossary-term__list">
      <div class="ap-glossary-term__entry">
        <dt id="gt-contrast" tabindex="-1"><dfn id="gt-dfn-contrast">Contrast ratio</dfn></dt>
        <dd>
          <p class="ap-glossary-term__short">How much lighter one color is than another, from 1:1 for no difference to 21:1 for black on white.</p>
          <p>It is worked out from the relative luminance of the two colors as <code>(L1 + 0.05) / (L2 + 0.05)</code>, where L1 is the lighter one.</p>
          <a class="ap-glossary-term__back" href="#gt-ref-contrast" aria-describedby="gt-dfn-contrast">Back to text</a>
        </dd>
      </div>
      <div class="ap-glossary-term__entry">
        <dt id="gt-wcag" tabindex="-1"><dfn id="gt-dfn-wcag"><abbr>WCAG</abbr></dfn></dt>
        <dd>
          <p class="ap-glossary-term__short">Web Content Accessibility Guidelines: the W3C standard that many accessibility laws refer to.</p>
          <p>Version 2.2 became a W3C Recommendation in October 2023. Its success criteria are graded A, AA and AAA.</p>
          <a class="ap-glossary-term__back" href="#gt-ref-wcag" aria-describedby="gt-dfn-wcag">Back to text</a>
        </dd>
      </div>
      <div class="ap-glossary-term__entry">
        <dt id="gt-large" tabindex="-1"><dfn id="gt-dfn-large">Large text</dfn></dt>
        <dd>
          <p class="ap-glossary-term__short">Text of at least 18 points, or 14 points in bold: about 24 and 18.66 CSS pixels.</p>
          <p>Bigger letters stay readable at lower contrast, so large text needs 3:1 rather than 4.5:1.</p>
          <a class="ap-glossary-term__back" href="#gt-ref-large" aria-describedby="gt-dfn-large">Back to text</a>
        </dd>
      </div>
      <div class="ap-glossary-term__entry">
        <dt id="gt-luminance" tabindex="-1"><dfn id="gt-dfn-luminance">Relative luminance</dfn></dt>
        <dd>
          <p class="ap-glossary-term__short">How bright a color is, from 0 for black to 1 for white, weighted for how the eye sees red, green and blue.</p>
          <p>Green counts for most of it and blue for least, which is why yellow text on white fails and pure blue on white passes.</p>
          <a class="ap-glossary-term__back" href="#gt-ref-luminance" aria-describedby="gt-dfn-luminance">Back to text</a>
        </dd>
      </div>
    </dl>
  </div>
</div>

WCAG 2.2

What it meets

The success criteria this pattern takes care of, and how.

  • 1.3.1 Info and Relationships Level A

    The glossary is a description list, each term in a dfn inside its dt, so terms and definitions are paired in the markup.

  • 1.4.13 Content on Hover or Focus Level AA

    Definitions open on a click or a key press, never on hover alone; once open they stay until dismissed, and Escape closes them without moving the pointer.

  • 2.1.1 Keyboard Level A

    Terms are buttons, so Enter and Space open them; Escape, Tab and the links all work from the keyboard.

  • 3.1.3 Unusual Words Level AAA

    Every technical term in the text has a definition one key press away and a full entry in the glossary.

  • 3.1.4 Abbreviations Level AAA

    The abbreviation WCAG is marked with abbr and expanded in its definition, in the toggletip and in the glossary.

  • 4.1.2 Name, Role, Value Level A

    Each term button reports aria-expanded, so its open or closed state is exposed.

  • 4.1.3 Status Messages Level AA

    The definition is written into a polite status region, so it is announced when it opens without moving focus.

Usage

When to use it

Use it

  • Docs, articles and reports with technical terms some readers know and others do not.
  • A first mention of a term, where a definition in place saves a trip to another page.

Use something else

  • Every repeat of the same term: mark the first use, and let the glossary serve the rest.
  • Long explanations: link to a page; a toggletip is for a sentence or two.
  • Labels of form fields and controls: put help text beside the field and tie it with aria-describedby.

Common failures

How it usually goes wrong

  • Definitions only in a title attribute

    A title tooltip appears on mouse hover only. Keyboard, touch and many screen reader users never see it. A button that opens the definition works for everyone.

  • A tooltip that vanishes on the way to it

    Hover tooltips close as the pointer moves onto them, and cannot hold a link. A toggletip stays open until it is dismissed.

  • Opening without saying anything

    If the definition appears silently, screen reader users have to go looking for it. The status region announces it the moment it opens.

  • No way back from the glossary

    A one-way link leaves readers stranded at the bottom of the page. Every entry links back to the term in the text, and focus follows.

  • dfn on every use

    dfn marks the place where a term is defined. In the glossary that is the dt; using it on each mention in the text says the text defines it.

  • Two copies of every definition

    A definition written in the toggletip and again in the glossary drifts apart. The toggletip here copies the glossary's short definition.

Notes

Building it

  • The status region is in the page, empty, before anything is written into it; a live region created at the same moment as its content is often not announced.
  • The script empties the region and fills it a moment later, so the same definition is announced again if the term is opened twice.
  • The definition closes when focus leaves the term and its toggletip, on Escape, and on a click elsewhere, but never on a timer.
  • Without the script the buttons do nothing, while the glossary still reads in full. If the text must work without scripts, make each term a link to its entry and turn it into a button from the script.
  • Each Back to text link is described by its term, so a list of links tells them apart.

Sources: Inclusive Components: Tooltips and toggletips · Understanding SC 3.1.3: Unusual Words · HTML: the dfn element

Checked with axe in light and dark themes, at desktop and phone widths, and by keyboard. Not yet tested with every screen reader and browser pair. Report a correction