One layout is seen differently by different people: one has enlarged the system font, one views it through a screen magnifier at 200%, one has turned on high-contrast mode, one has disabled animations because of a vestibular condition, one has opened the site on a narrow phone. The product page interface must survive all of these settings, not only the view from the designer's mockup.
The naive approach is to build it pixel-for-pixel for one perfect screen. That is natural: this is how the approved mockup looks, everything on it is beautiful, and it seems enough to reproduce it precisely in markup.
This breaks at the very first user setting. When text is enlarged to 200% (1.4.4), fixed heights clip the lines; on a narrow screen the content must reflow into a single column with no horizontal scroll (1.4.10 - reflow down to 320px); with user-set spacing the text must not overlap itself (1.4.12); and in forced-colors mode the system throws out your colours and substitutes its own - and everything that rested on colour falls apart.
The first thing to check is contrast. Normal text must differ from the background by at least 4.5:1, large text (from 24px or 18.66px bold) by 3:1 (1.4.3). But the rule reaches wider than text: field borders, icons, the focus indicator and states must give at least 3:1 against the adjacent colour (1.4.11). A pale-red sale price on white looks stylish and fails both thresholds.
| What | Minimum contrast |
|---|---|
| Normal text | 4.5:1 |
| Large text (24px, or 18.66px bold) | 3:1 |
| Icons, borders, focus indicator | 3:1 |
Colour must not be the only carrier of meaning (1.4.1). If 'out of stock' is shown only by a grey tone, a colour-blind person cannot tell it apart - text or an icon is also needed. The same goes for form errors and required fields: alongside colour there is always duplicating text or an icon.
Motion is a concern of its own. In some people animation causes nausea and dizziness (vestibular disorders), so the system emits the prefers-reduced-motion: reduce request, and it must be respected - kill the parallax, the auto-scrolling carousels, and abrupt transitions (2.3.3 and 2.2.2). At the same time motion must not be the only carrier of meaning: if a loading status is visible only through a spinning spinner, with animation off it disappears.
A promo video carries three more requirements. Speech in the video is duplicated by captions - otherwise a deaf user gets no content (1.2.2); a text transcript is also desirable. Important visual information not spoken aloud is provided through audio description (1.2.5). Sound must not start by itself, and the player must have pause and volume controls (1.4.2).
Images fall into two classes. A decorative one - a background, a divider, an ornament - gets an empty alt so the screen reader skips it and does not read the file name. A meaningful one - a product photo, a sale badge, a size chart - gets a short functional alternative: not 'IMG_2043' but what the image conveys and why it is here (1.1.1).
The price for all this is testing across several modes, not in one browser on a large monitor. You must check not only the body text but also the icons, the field borders, the focus indicator and the states - these most often fail contrast. It is a routine easy to skip under a deadline, but it is the very difference between 'works on my machine' and 'works for everyone'.
A typical failure assembles itself out of small things at once: a low-vision buyer enlarges the page to 200%, the layout breaks into horizontal scroll, the sale price is unreadable because of its pale colour, and the promo video autoplays with sound and no captions. Each detail on its own seems cosmetic - together they throw the person out of the purchase. That is why visual accessibility is checked under the conditions the users live in: with a magnifier, a large font, animation off, and in high-contrast mode.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
transition-duration: .01ms !important;
transition-delay: -1ms !important;
scroll-behavior: auto !important;
}
}