Topic 03

Contrast, Motion and Zoom

AccessibilityCSS

Much of accessibility is visual, and most of the visual part can be measured. Is the text dark enough against its background? Does the page still work when someone zooms in? Does anything flash or slide in a way that can make a person ill? Is every button big enough to hit, and can you always see which one has focus? Each question has a number or a clear rule in WCAG, and each can be checked in minutes.

Road signs solved this problem long ago. They use strong contrast, they are readable from far away, and they never rely on colour alone: a stop sign has its own shape and its word as well as its red. That is because everyone passes them, in fog, in low sun, with good eyes and bad. A web page has more to survive than a sign: it can also be zoomed, restyled and read aloud, and each of those has to keep working.

What Is a Contrast Ratio?

The contrast ratio compares how light two colours are, on a scale from 1 to 1, the same colour twice, up to 21 to 1, black on white. WCAG level AA asks for at least 4.5 to 1 between normal text and its background. Large text, at least 24 pixels, or about 18.5 pixels if bold, needs 3 to 1, because big letters are easier to read. The same 3 to 1 applies to the parts of controls you need to see to use them, such as a button's edge or a focus ring, against the colours beside them.

Fragment
.note-passes {
  color: #767676;  /* 4.54 to 1 on white: passes AA */
}

.note-fails {
  color: #999999;  /* 2.85 to 1 on white: fails */
}

Both greys look readable to many people on a good screen, and one of them fails. The first, a middle grey, passes for normal text with almost nothing to spare. The second, a lighter grey of the kind often used for captions and dates, falls far short. Put each on a white page and a low-vision reader, or anyone reading a phone in sunlight, struggles with the second.

You do not have to calculate any of this. In DevTools, select a text element, and in the Styles pane click the small colour square beside its color value. The colour picker that opens shows the contrast ratio against the background, with a tick or a cross for the AA and AAA levels. Drag the colour darker in the picker and watch the ratio climb past 4.5.

The site's colours pass comfortably. Chapter 3's text colour on white measures about 15.8 to 1, and the dark theme from Chapter 5 about 15 to 1. The accent colour, used for links, the pressed filter button and the focus ring, measures 6.7 to 1 on the light background and 8.9 to 1 on the dark one. One thing to check: if you kept Chapter 3's firebrick focus outline instead of Chapter 9's accent one, it measures 6.7 to 1 on white but only 2.8 to 1 on the dark background, so it fails in the dark theme. Switch it to the accent token and it passes in both.

The site's colours against the AA minimums
WhatMinimum ratio (AA)The site's value, light / dark
Body text4.5 : 115.8 : 1 / 15.0 : 1
Large heading3 : 115.8 : 1 / 15.0 : 1
Pressed filter button against the page3 : 16.7 : 1 / 8.9 : 1
Focus ring in the accent colour3 : 16.7 : 1 / 8.9 : 1

Why Is Colour Alone Not Enough?

About one man in twelve, and far fewer women, has some form of colour blindness, most often difficulty telling red from green. Others use high-contrast modes that replace a page's colours altogether. So WCAG's rule is that colour must never be the only way information is shown. An error marked only by a red border, or a link picked out from the text around it only by its colour, fails that rule.

Fragment
<!-- Colour only: the border turns red, nothing else changes -->
<input id="email" name="email" type="email" class="has-error">

<!-- Colour, words and a symbol -->
<input id="email" name="email" type="email" class="has-error"
       aria-invalid="true" aria-describedby="email-error">
<p id="email-error">
  <span aria-hidden="true">⚠</span> Enter an email address, such as you@example.com.
</p>

In the first version, a visitor who cannot tell red from grey sees an ordinary field and has no idea anything is wrong, and a screen reader says nothing at all. In the second, the red border is still there, but a warning symbol and a sentence sit under the field, saying what is wrong and how to fix it. The symbol is hidden from screen readers, which would otherwise read out its name; they hear the sentence, linked to the field as in Chapter 10. The site's contact form does not rely on its red border alone either: when you send it, the browser's own message bubble says in words what is wrong, and the message box gets a sentence of its own underneath.

Links follow the same rule. Browsers underline links by default, and that underline is what tells a colour-blind reader where a link is inside a sentence. Keep it for links in running text; a menu of links in the header is recognisable by its position and does not need it.

What Happens When Someone Zooms In?

Many people read the web zoomed in. WCAG asks for two things. Text must still work at 200 percent zoom, with nothing cut off or overlapping. And the page must reflow at a width of 320 CSS pixels: everything still readable and usable with vertical scrolling only, never scrolling sideways to read each line. That width is what a common 1280-pixel window becomes at 400 percent zoom, and roughly the width of a small phone.

What the browser shows
At 320 pixels wide (DevTools device toolbar):
  The nav links wrap onto a second line.
  The project grid shows one card per row.
  Nothing needs scrolling sideways.

At 200% zoom in a desktop window:
  The text is twice the size and rewraps to the narrower space.
  The grid drops to fewer columns.

To see it yourself, open the device toolbar in DevTools and set the width to 320, then scroll the whole page on each of the three pages. Then close it, and zoom the ordinary window to 200 percent with Ctrl and the plus key on Windows or Cmd and plus on macOS. On the site, nothing breaks, and that is not luck. Text sizes in rem from Chapter 3 grow with zoom; the wrapping nav from Chapter 4 and the auto-fitting grid from Chapter 5 rearrange themselves.

The usual causes of failure are the opposite habits: a card with a fixed height, so larger text spills out of the bottom; a container with a fixed width in pixels, so the page scrolls sideways; and headings sized only in vw, which Chapter 5 showed do not grow with zoom at all.

Can Motion Be a Problem?

For some people it is. Chapter 5 turned off the cards' rising movement for visitors whose system asks for reduced motion, using prefers-reduced-motion. Keep that rule in mind for anything you animate later: movement across the screen can cause dizziness and nausea for people with vestibular disorders.

Flashing is more serious. Content that flashes more than three times in any one second can trigger seizures in people with photosensitive epilepsy, and WCAG puts this rule at level A, the floor. The site has nothing that flashes. Keep it that way, including in any video or animated image you add.

Are the Controls Big Enough, and Is Focus Visible?

WCAG 2.2 added a minimum target size at level AA: anything you click or tap should be at least 24 by 24 CSS pixels, or have enough space around it that a slightly missed tap does not hit a neighbour. Links inside a sentence are an exception. Check the smallest controls on the site, the filter buttons and the theme button, by hovering over them with the DevTools element picker, which shows each one's size.

It also added a rule about hidden focus. The sticky header from Chapter 4 stays on top of the page as it scrolls. When a keyboard user moves back up the page with Shift and Tab, the browser scrolls just far enough to show the focused link at the top of the window, which is exactly where the header sits, so the link can end up hidden underneath it. WCAG AA forbids the focused element being hidden completely.

css/style.css
html {
  scroll-padding-top: 6rem;
}

This one rule tells the browser that the top 6 rem of the window is covered, so whenever it scrolls something into view, including the element that receives focus, it stops that much lower. Scroll to the bottom of a long page and press Shift and Tab now, and each focused link appears below the header instead of behind it. Set the value a little larger than your header's height, which DevTools shows when you hover over the header.

Common Confusions
  • "It looks readable to me." Your eyes, your screen and your lighting are one case among many. Contrast has to work for low vision and for a phone in bright sun, so measure it.
  • "A dark theme is automatically accessible." Dark themes fail contrast as easily as light ones. A colour that passes on white, like a firebrick focus ring, can fail on a near-black background.
  • "Zoom is the browser's problem." The browser enlarges the page, but fixed heights, fixed widths and text sized only in viewport units are yours, and they are what breaks.
Why It Matters
  • Low contrast is the most common accessibility failure found on real sites, and these are among the cheapest to fix: a colour value, a unit, one line of CSS.
  • By the end of this page the site passes each check in both themes, and you can prove it with the numbers.

Knowledge Check

What contrast does WCAG level AA ask for between normal body text and its background?

  • At least 3 to 1 against its background
  • At least 7 to 1 against its background
  • At least 4.5 to 1 against its background
  • At least 2 to 1 against its background

A form shows errors only by turning the field's border red. What is the problem?

  • Some visitors cannot perceive the change at all
  • Red borders are not supported in every browser
  • Red cannot be shown in the site's dark theme
  • Screen readers read the colour name aloud wrongly

What does WCAG's reflow rule ask of a page at a width of 320 CSS pixels?

  • The text shrinks until the whole page fits
  • A separate mobile page is shown instead
  • Images are hidden to leave room for the text
  • It works without any scrolling sideways

Is a dark theme automatically accessible?

  • Yes; light text on dark always has high contrast
  • No; its colour pairs need measuring like any others
  • Yes, as long as the system setting switches it on
  • No; dark themes always fail WCAG's contrast rules

You got correct