# Accessibility settings that need the feature they turn on

Source: https://easeweb.dev/learn/accessibility-settings
Topics: Page structure > Accessibility settings can be turned on without the feature they provide (EN 301 549 5.2)
The fix: Either put each setting where someone with the need it serves can reach it before it is on: at the start of the header, before anything it changes, drawn at the contrast and size of the site's high contrast mode; or also turn each setting on from the device's matching setting. The device settings reach only people who have turned them on, so they need switches everyone else can reach beside them.
Test with: zoom, contrast measurement, reduced motion, keyboard
References: https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf https://www.w3.org/WAI/WCAG22/Understanding/contrast-enhanced.html https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-pressed https://www.w3.org/WAI/people-use-web/user-stories/

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

## What happens

Some sites offer settings of their own: a high contrast mode, larger text, a pause for animations, captions, an easy-read version. Each is there for people who can't use the site as it is, so the switch that turns a setting on is used by exactly those people, before the setting is on, in the look and layout it is there to change. A switch that needs what its setting provides can't be used by anyone who needs the setting.

Riverside Library, a small public library, offers two settings on its quiet, modern site: a high contrast mode, with white text on black and yellow links, for readers who find its grey text hard to read, and a switch that pauses its animations, for readers who can't read while its banner of this week's events changes every few seconds.

The high contrast switch sits in the header, after the menu, set like the rest of the header's small print: 12 pixels, in #767676 grey, with no border. A reader with low vision opens the site to check the opening hours. The large heading is readable. The switch at the far end of the header, the one thing that would make the rest of the page readable for them, is a faint smudge, and with a screen magnifier showing only the top left of the page, it is off screen altogether.

The pause switch is easy to read, so its problem is a different one. It sits in the footer, after the events banner and the rest of the page. A reader who can't take in text while something moves beside it has to read past the banner, or press Tab through every link in it, to reach the one switch that stops it.

## Why it fails

First, what the standard doesn't ask: EN 301 549 doesn't require a website to offer a high contrast mode, a text size control, a pause switch or any other setting. A site's own design has to meet WCAG 2.1 A and AA through clause 9 of EN 301 549 whether it has settings or not, so the standard look must already have enough contrast and enlarge without breaking. The settings come on top of that.

What it does ask comes in clause 5.2: where a product has documented accessibility features, it must be possible to turn on the ones a need calls for "without relying on a method that does not support that need". The test is the same for every setting: ask what the setting provides, then check that its switch doesn't need it. A captions switch must not need hearing, a screen reader mode must not need sight, and a keyboard mode must not need a mouse. The library's two switches fail the test in two ways. The high contrast mode is for people who can't read the standard look, and its switch is drawn in the standard look's faintest type. The pause switch is for people who can't cope with the motion, and it can only be reached after it.

The clause applies to web content that has documented accessibility features, which a site has once it describes a setting in its accessibility statement or help pages, the places EN 301 549 12.1.1 names for that information. It isn't in WCAG, so a site can meet every WCAG criterion here and still fail it. The footer switch, for instance, is a way to pause the banner, which is what WCAG 2.2.2 asks for, and the Understanding page for 2.2.2 says nothing about where that way must be.

## Who is affected

The failure reaches whoever a setting is for, and every group has settings made for it, so the same mistake can shut out anyone. The library's two switches shut out people with low vision and people whom motion stops from reading, including many people with attention difficulties; the notes show how other settings, placed the same way, reach everyone else. Motion can also make people with vestibular disorders dizzy or sick, and for them, reaching a switch after the motion means sitting through the thing they need to avoid.

## What automation and AI miss

Checkers hold a settings switch to the page's own standard, never to what its setting is for. The high contrast switch's grey is 4.54:1 on white, which meets the 4.5:1 that WCAG 1.4.3 asks of text, so axe and every other contrast checker pass it at AA. The pause switch is named, readable and reachable with Tab, so it passes too. No checker knows that these buttons are the way into settings. This audit sends a review lead when a page has a control named for an accessibility setting, such as High contrast, Pause animations, Text size or 文字サイズ, so a person checks it with the need in mind. It can't tell whether someone with that need would reach the control.

AI tools asked to "add a high contrast toggle" or "add a way to pause animations" may put one in the header styled like the links around it, or in the footer with the site's other links, as many sites do. They have no way to ask who the switch is for.

## Before: a switch drawn in the look it replaces

```html
<header>
  <a href="/" class="logo">Riverside Library</a>
  <nav>…</nav>
  <div class="tools">
    <button type="button" id="contrast" aria-pressed="false">High contrast</button>
  </div>
</header>
```

```css
.tools button {
  font-size: 12px;
  color: #767676;
  background: none;
  border: 0;
}
.high-contrast body { background: #000; color: #fff; }
.high-contrast a, .high-contrast .tools button { color: #ff0; }
```

```js
const contrast = document.getElementById('contrast');
contrast.addEventListener('click', () => {
  const on = contrast.getAttribute('aria-pressed') !== 'true';
  contrast.setAttribute('aria-pressed', on);
  document.documentElement.classList.toggle('high-contrast', on);
});
```

The high contrast switch is the faintest, smallest text in the header and the last thing in it, so finding it takes the eyesight the mode is there to replace.

## Before: a switch placed after what it stops

```html
<header>
  <a href="/" class="logo">Riverside Library</a>
  <nav>…</nav>
</header>
<main>
  <div class="events">…</div>
  …
</main>
<footer>
  …
  <button type="button" id="motion" aria-pressed="false">Pause animations</button>
</footer>
```

```css
.events .slide { animation: rotate 12s infinite; }
.still .events .slide { animation: none; }
```

```js
const motion = document.getElementById('motion');
motion.addEventListener('click', () => {
  const on = motion.getAttribute('aria-pressed') !== 'true';
  motion.setAttribute('aria-pressed', on);
  document.documentElement.classList.toggle('still', on);
});
```

The pause switch is clear to read, but it comes after the banner and the whole page, both on screen and in the Tab order, so reaching it means getting past the motion it is there to stop.

## After: settings first, usable before they are on

```html
<header>
  <div class="tools">
    <button type="button" id="contrast" aria-pressed="false">High contrast</button>
    <button type="button" id="motion" aria-pressed="false">Pause animations</button>
  </div>
  <a href="/" class="logo">Riverside Library</a>
  <nav>…</nav>
</header>
<main>
  <div class="events">…</div>
  …
</main>
```

```css
.tools button {
  font-size: 18px;
  font-weight: 700;
  color: #000;
  background: #fff;
  border: 2px solid #000;
  border-radius: 6px;
  padding: 6px 14px;
}
.high-contrast body { background: #000; color: #fff; }
.high-contrast a, .high-contrast .tools button { color: #ff0; }
.high-contrast .tools button { background: #000; border-color: #ff0; }
.events .slide { animation: rotate 12s infinite; }
.still .events .slide { animation: none; }
```

```js
for (const [id, mode] of [['contrast', 'high-contrast'], ['motion', 'still']]) {
  const button = document.getElementById(id);
  button.addEventListener('click', () => {
    const on = button.getAttribute('aria-pressed') !== 'true';
    button.setAttribute('aria-pressed', on);
    document.documentElement.classList.toggle(mode, on);
  });
}
```

Each switch can now be used by someone who needs its setting, before the setting is on. Both are the first thing in the header, where a magnifier starts and where Tab arrives first, and before the banner, so the motion can be stopped before it has to be watched. They are drawn the way the high contrast mode draws text: 18 pixels and bold, black on white at 21:1 inside a black border, and yellow on black once the mode is on.

## After: also follow the device's settings

```html
<header>
  <a href="/" class="logo">Riverside Library</a>
  <nav>…</nav>
  <div class="tools">
    <button type="button" id="contrast" aria-pressed="false">High contrast</button>
  </div>
</header>
<main>
  <div class="events">…</div>
  …
</main>
<footer>
  …
  <button type="button" id="motion" aria-pressed="false">Pause animations</button>
</footer>
```

```css
.tools button {
  font-size: 12px;
  color: #767676;
  background: none;
  border: 0;
}
.high-contrast body { background: #000; color: #fff; }
.high-contrast a, .high-contrast .tools button { color: #ff0; }
.events .slide { animation: rotate 12s infinite; }
.still .events .slide { animation: none; }
```

```js
for (const [id, mode, query] of [
  ['contrast', 'high-contrast', '(prefers-contrast: more)'],
  ['motion', 'still', '(prefers-reduced-motion: reduce)']
]) {
  const button = document.getElementById(id);
  const asked = matchMedia(query);
  const set = (on) => {
    button.setAttribute('aria-pressed', on);
    document.documentElement.classList.toggle(mode, on);
  };
  set(asked.matches);
  asked.addEventListener('change', (event) => set(event.matches));
  button.addEventListener('click', () => set(button.getAttribute('aria-pressed') !== 'true'));
}
```

Someone who has turned on their device's increase contrast or reduce motion setting gets the high contrast look, or a still banner, as soon as the page opens, without looking for anything, and the switch shows the setting as on and can still turn it off. This reaches only people who have those settings on: anyone else, including a reader on a library computer they can't change, still has to find the faint switch and get past the banner to the pause, so this needs the first fix beside it.

## Which option to use

Use the first: switches drawn at the high contrast mode's own contrast and size, at the start of the header and before the banner, work for everyone who comes to the site, whatever their device is set to. The second is worth adding to it, because a reader who has already told their device what they need shouldn't have to tell every site again, but on its own it leaves out everyone who hasn't, so it is not enough.

## Implementation decisions

The same rule holds for every setting a site offers: the way to turn it on must not depend on the thing it fixes. Some other common cases:

- A text size control set in small type is the same mistake as the library's high contrast switch. Draw it at least at body size, and set the site's text in rem so the browser's own text size setting works too, with boxes that grow with the text, as [enlarged text cut off by fixed-height boxes](/learn/resize-text) explains.
- A "Captions" or "Sign language" option explained only in a video's narration is lost on the people it is for. Put the option on the player's bar, as a button with a visible label.
- An easy-read version or a "Listen" button announced only in a long paragraph is missed by the readers who need it. Give it a short, plain label and an icon, at the top of the page.

Keep each control looking the same whether its setting is on or off, apart from its colours, so people can find it again to turn the setting off. Mark its state with aria-pressed, and keep its name the same: "High contrast" pressed or not pressed, never a label that changes to "Standard contrast". Remember the choice with a cookie or local storage, so it holds on the next page.

The banner should also stay still for people whose device asks for less motion even without the switch, as [animations that ignore the reduced-motion setting](/learn/reduced-motion) explains, and a pause that only covers one banner doesn't help with motion elsewhere on the page: make the switch stop every animation the site runs.

Windows contrast themes work differently: whatever the site's own mode does, they replace the site's colours with the user's own through forced colors, which the site should allow for, as [high contrast mode hiding focus, icons and selections](/learn/forced-colors) explains. A site's own high contrast mode is for everyone else, which is why its switch has to be easy to see.

A floating accessibility overlay with its own panel of settings doesn't fix this, and can repeat it: the launcher is a small icon, and its panel's switches are set in small type. The settings that matter most, contrast, text size and motion, are better built into the site's own design, where they can be tested.

## Verify the fix

1. For each setting the site offers, name the need it is for. Then, with the setting off, find and reach its switch from the top of the home page the way someone with that need would: at 400% zoom or with a screen magnifier for contrast and text size, with Tab and without watching the page for anything that moves, with the sound off for captions. Each switch comes before the main menu and before anything it changes.
2. Measure the text of each control for a visual setting, such as contrast or text size: at least 16 pixels, at least 7:1 against its background, with a border or fill of at least 3:1, in both the standard and the high contrast look.
3. Turn on the device's increase contrast setting (macOS or iOS) and its reduce motion setting, and open the site: it opens in its high contrast look with the banner still, and each control shows as pressed and can turn its setting off.
4. Turn each setting off again from its own switch, and confirm the switch is as easy to find and reach while its setting is on.

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after any redesign of the header, the settings or the animations.

## Limits

This guide covers a site's own accessibility settings and the way to turn them on. It doesn't cover the contrast of the site's standard look, which WCAG 1.4.3 covers in [low-contrast text on brand colours, photos and hover states](/learn/text-contrast), the pause that WCAG 2.2.2 asks for in [tickers, carousels and animations that can't be paused](/learn/moving-content), or how the high contrast mode itself must keep focus, icons and selections visible. EN 301 549 5.2 applies only to features a product documents, so a site with no settings has nothing to fail here, but that is no reason to drop a setting that some readers rely on. Test with the people each setting is for, with their own devices and settings.

---

Get this guide in your coding agent: MCP https://easeweb.dev/mcp (setup at https://easeweb.dev/services/developers)
