# Striped backgrounds and op-art hero images that seem to move

Source: https://easeweb.dev/learn/striped-backgrounds
Topics: Time limits and motion > Backgrounds and hero images have no large, high-contrast stripes (best practice; related to WCAG 2.3.1)
The fix: Either size the stripes in percentages, so the hero holds four broad pairs at any width, or keep the fine stripes in two close tints, less than a tenth of white's luminance apart. Keeping the bold stripes to a small tile also stays under the area, up to 150% zoom.
Test with: zoom, contrast measurement, flash analysis
References: https://www.w3.org/WAI/WCAG22/Understanding/three-flashes-or-below-threshold.html https://www.w3.org/TR/WCAG22/#dfn-general-flash-and-red-flash-thresholds https://www.itu.int/rec/R-REC-BT.1702 https://pubmed.ncbi.nlm.nih.gov/16146438/ https://pubmed.ncbi.nlm.nih.gov/16060930/ https://pubmed.ncbi.nlm.nih.gov/871807/ https://www1.essex.ac.uk/psychology/overlays/1999-141.pdf https://pmc.ncbi.nlm.nih.gov/articles/PMC6867050/ https://www.tcnet.ne.jp/wp-content/uploads/community_ch/broadcasting-plan-standard/standard_Exhibit.pdf https://epilepsysociety.org.uk/sites/default/files/2025-04/PhotosensitiveepilepsyApril2025.pdf https://developer.mozilla.org/en-US/docs/Web/Accessibility/Guides/Accessibility_and_Spatial_Patterns https://www.w3.org/TR/css-values-4/#reference-pixel https://www.w3.org/TR/wcag-3.0/#dfn-pseudo-motion https://github.com/w3c/wcag3/issues/739 https://github.com/electronicarts/IRIS

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, and nothing here is medical advice.

## What happens

A fabric shop launches its summer collection. The designer wants the home page to feel graphic and modern, so the hero is drawn in bold op-art: black and white vertical stripes, each 8 pixels wide, across the full width of the page, with a white card in the middle that reads "The summer edit" and a "Shop the edit" button. Nothing moves. Look at it for a few seconds, though, and the stripes start to shimmer: the edges bend, faint colours run along them, and the whole hero seems to drift. The same failure turns up as an op-art photo or illustration of rings or checks in a hero, a checkerboard or houndstooth background copied from a pattern gallery, a dot grid set close across a section, and stripes one pixel wide that turn into uneven bands when the page is zoomed or scrolled.

## Why it fails

No success criterion fails here, and this guide is a best practice. Success criterion 2.3.1 Three Flashes or Below Threshold counts flashes, pairs of opposing changes in brightness over time, and a still image has none, so the hero passes it whatever its contrast and size. Its Understanding document mentions patterns only to exempt fine, balanced ones that flash, such as white noise or an alternating checkerboard. The draft of WCAG 3 adds a requirement against pseudo-motion, defined as static content that gives the perception or feeling of motion, but it is still in development.

The thresholds come from television. The Epilepsy Foundation of America's expert consensus (Harding, Wilkins and others, 2005) treats a pattern as able to provoke seizures when it has clearly visible stripes, more than five light-dark pairs in any orientation. When the stripes cover more than 0.006 steradians from the closest expected viewing distance, the lightest stripe is brighter than 50 cd/m², and the pattern shows for half a second or more, it should have no more than five pairs if it changes direction, oscillates, flashes or reverses, and, if it is unchanging, "no more than eight stripes". ITU-R BT.1702-3 adds that stripes may be parallel or radial, curved or straight, or formed by rows of repeated elements such as polka dots, and in its informative annex it counts a pattern as harmful only when its light and dark bars differ in brightness as much as a harmful flash, and, for a still pattern, only when it fills more than 40% of the screen, a looser area than the quarter the consensus uses. Japan's broadcasters ask for something similar, without figures: NHK and the commercial broadcasters' guideline on animation and other techniques asks them to avoid regular patterns, such as stripes, spirals and concentric circles, that fill most of the screen.

WCAG counts a flash with the same figures in its own terms. It defines 0.006 steradians as a quarter of a 10-degree field, which W3C estimates as 341 × 256 CSS pixels, and a general flash as a change of a tenth of white's relative luminance or more. Applying those to a still pattern is this guide's reading, not a rule anyone has written for the web. By it, the hero fails on every count. Its stripes are black (relative luminance close to 0) and white (1), it holds 80 light-dark pairs at 1,280 pixels wide, and it fills far more than a quarter of the field. At arm's length a CSS pixel is about 0.0213 degrees, so each pair spans about a third of a degree: close to 3 cycles per degree, the spacing Arnold Wilkins and his colleagues found most likely to cause discomfort, illusions and seizures.

## Who is affected

Pattern sensitivity is found in most people with photosensitive epilepsy, and matters clinically for about 30 to 50% of them; in one study, 11 of 32 photosensitive patients reacted to still patterns. Stripes at about 3 cycles per degree can also make most people see illusions of colour, shape or movement, and give people with migraine headaches. The Epilepsy Society lists images on screens with a contrasting dark and light pattern, such as black and white stripes or checks, as a possible trigger, and W3C's cognitive accessibility task force names diagonal lines in a background and optical illusions among the pseudo-motion it wants WCAG 3 to cover. A phone held close makes the hero fill even more of what someone sees.

## What automation and AI miss

The audit finds nothing here. Its flash check steps through animations and counts changes over time, and this hero never changes. axe, and Lighthouse, which runs axe's rules, have no rule for patterns, and no WCAG criterion gives them one, so the page passes. An AI asked to review the page against WCAG has no reason to raise it either. Meanwhile pattern galleries, such as Lea Verou's CSS3 Patterns Gallery, offer stripes, checkerboards, houndstooth and polka dots as backgrounds to copy, with nothing said about their size or contrast. IRIS, EA's open-source library, checks video for harmful spatial patterns as well as flashes, so a recording of the page can go through it; a person still has to look for patterns in images and count them.

## Before: fine black and white stripes

```html
<section class="hero">
  <div class="hero-card">
    <h1>The summer edit</h1>
    <p>Linen, cotton and canvas, made to last.</p>
    <a href="/summer">Shop the edit</a>
  </div>
</section>
```

```css
.hero {
  display: grid;
  place-items: center;
  min-height: 24rem;
  padding: 4rem 1.5rem;
  background: repeating-linear-gradient(90deg, #111 0 8px, #fff 8px 16px);
}
.hero-card {
  max-width: 28rem;
  padding: 2rem;
  border: 2px solid #111;
  background: #fff;
  text-align: center;
}
```

- The stripes are 8 pixels wide and repeat every 16, so the hero holds 80 light-dark pairs at 1,280 pixels wide, and more on a wider screen.
- Black against white is close to the strongest contrast a screen can show.
- They fill the whole hero around the card, far more than a quarter of a 341 × 256 pixel field.
- Nothing moves, so no checker reports it.

## After: a few broad stripes

```html
<section class="hero">
  <div class="hero-card">
    <h1>The summer edit</h1>
    <p>Linen, cotton and canvas, made to last.</p>
    <a href="/summer">Shop the edit</a>
  </div>
</section>
```

```css
.hero {
  display: grid;
  place-items: center;
  min-height: 24rem;
  padding: 4rem 1.5rem;
  background: repeating-linear-gradient(90deg, #111 0 12.5%, #fff 12.5% 25%);
}
.hero-card {
  max-width: 28rem;
  padding: 2rem;
  border: 2px solid #111;
  background: #fff;
  text-align: center;
}
```

1. Give the stripe widths in percentages of the hero: 12.5% each, so one light-dark pair is a quarter of its width. The hero holds four pairs at any screen width, under the five both sets of guidelines count from.
2. Keep the black and white. Each pair is now 320 pixels wide on a 1,280-pixel screen, about 7 degrees at arm's length: far coarser than the spacing that troubles people most.

This fixes the Before at every width and zoom, and keeps the bold black and white look. 2.3.1 still passes, since nothing flashes.

## After: soft stripes

```html
<section class="hero">
  <div class="hero-card">
    <h1>The summer edit</h1>
    <p>Linen, cotton and canvas, made to last.</p>
    <a href="/summer">Shop the edit</a>
  </div>
</section>
```

```css
.hero {
  display: grid;
  place-items: center;
  min-height: 24rem;
  padding: 4rem 1.5rem;
  background: repeating-linear-gradient(90deg, #ebe5da 0 8px, #f5f1ea 8px 16px);
}
.hero-card {
  max-width: 28rem;
  padding: 2rem;
  border: 2px solid #111;
  background: #fff;
  text-align: center;
}
```

1. Change the two colours to two close tints of linen: `#ebe5da` and `#f5f1ea`, relative luminance 0.79 and 0.88. They are 0.095 apart, under a tenth of white's luminance, so the stripes read as a woven texture rather than a grating.
2. Leave the card as it is: its black text and border on white keep their contrast.

This keeps the fine stripes and changes two values. It stays below the brightness difference BT.1702 counts for a harmful pattern, but the Epilepsy Foundation of America's consensus counts clearly visible stripes whatever their contrast, and the hero still holds 80 of them. Treat it as enough for a pattern people only glimpse, and widen the stripes as well where the hero is the first thing on a page.

## After: bold stripes on a small tile only

```html
<section class="hero">
  <div class="hero-card">
    <span class="hero-mark"></span>
    <h1>The summer edit</h1>
    <p>Linen, cotton and canvas, made to last.</p>
    <a href="/summer">Shop the edit</a>
  </div>
</section>
```

```css
.hero {
  display: grid;
  place-items: center;
  min-height: 24rem;
  padding: 4rem 1.5rem;
  background: #f5f1ea;
}
.hero-card {
  max-width: 28rem;
  padding: 2rem;
  border: 2px solid #111;
  background: #fff;
  text-align: center;
}
.hero-mark {
  display: block;
  width: 6rem;
  height: 6rem;
  margin: 0 auto 1rem;
  background: repeating-linear-gradient(90deg, #111 0 8px, #fff 8px 16px);
}
```

1. Set the hero on plain linen, `#f5f1ea`, with no pattern.
2. Draw the original stripes on a 96-pixel square above the heading. It covers 9,216 square pixels, about 11% of a 341 × 256 field, well under a quarter.

This keeps the op-art look as a brand mark, but it passes only while the tile stays small. At 150% zoom it covers about 24% of the field; at 200% it covers 42%, over the quarter. Anyone who looks straight at it, or holds a phone close, still sees six pairs of fine black and white stripes.

## Which option to use

All three stay under the thresholds on a laptop at 100% zoom. The broad stripes are the recommended one: they keep the black and white and stay under both sets of guidelines at every width and zoom, with nothing to keep in check, while the other two are each partial. Soft stripes keep the fine texture by changing two colours, but the hero still holds dozens of visible stripes; choose them when the pattern is in the background of a page rather than its first view. The small tile keeps the bold fine stripes as a mark, and stays safe only while it stays small. A plain colour or a photograph with no regular pattern needs no measuring at all.

## Implementation decisions

Count the pairs where the eye meets them. A stripe width in pixels means a wider screen shows more stripes, so a hero that looks safe in the design file at 1,280 pixels can hold twice as many on a 2,560-pixel monitor; a width in percentages, or in `em` on a box of fixed size, keeps the count fixed. A `repeating-radial-gradient` draws rings, counted from the centre out, and a checkerboard counts along its rows and its columns. BT.1702 counts rows of repeated elements as stripes, so a grid of dots or icons set close in strong contrast is a pattern too.

Never draw stripes one or two pixels wide. In Chromium at a 125% display scale, or at 90% zoom, stripes 1 CSS pixel wide are drawn as uneven runs of one and two device pixels, so the pattern turns into bands the design never had, and the bands change place as the page scrolls: a still pattern that shimmers as it moves. Stripes several pixels wide are rounded too, but by a small part of their width, so they keep their shape.

An op-art image holds the pattern in its pixels, so CSS can't change it. Count its stripes at each size the page shows it, since a responsive image is scaled and cropped differently on each screen. Then fix the image: crop to fewer bands, soften the contrast, or choose another. An SVG pattern drawn with `patternUnits="userSpaceOnUse"` repeats in the SVG's own units, which are pixels when the SVG has no `viewBox`, and then gains stripes on a wider screen, as a CSS gradient in pixels does; `objectBoundingBox` scales the tiles with the shape.

Some changes look like fixes and are not. A switch to hide the pattern, a warning, or a pattern drawn only inside `prefers-reduced-motion: no-preference` leaves the pattern on screen for everyone who hasn't used the switch or turned the setting on, and it works from the first glance. Text set over the stripes, rather than on the card, has a contrast problem of its own: see [low-contrast text on brand colours, photos and hover states](/learn/text-contrast).

Stripes that really move are another failure: a scrolling or rotating pattern is covered by [tickers, carousels and animations that can't be paused](/learn/moving-content), an animated striped loader by [pulsing buttons, glowing badges and endless animations](/learn/endless-animations), and parallax by [animations that ignore the reduced-motion setting](/learn/reduced-motion). A pattern that flashes or reverses its contrast is counted under 2.3.1 in [flashing banners and videos that can trigger seizures](/learn/flashing-content).

## Verify the fix

1. List every pattern on the page: CSS repeating gradients and tiled backgrounds, hero images, illustrations, video stills, and grids of dots or icons.
2. For each pattern that covers a large area, count its light-dark pairs across the largest view, at the widest screen you support. Five or fewer passes; more goes to step 3.
3. Measure the relative luminance of its lightest and darkest parts. A difference under 0.10 passes; more goes to step 4.
4. Measure the area the pattern covers at the largest zoom people use: under a quarter of a 341 × 256 CSS pixel field passes.
5. Zoom to 200% and to 90%, and scroll slowly past each pattern: no stripes break into uneven bands or crawl as the page moves.

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the design, a campaign image or the pattern library changes.

## Limits

This is a starting pattern, not a guarantee for every application, and not medical advice. The thresholds were written for television viewed across a room, and carrying them to a web page, through WCAG's own estimate of a 10-degree field, is this guide's reading; a phone held close or a large monitor changes how much of the view a pattern fills. Keeping under them lowers the risk without removing it: the pattern guidelines Wilkins, Emmett and Harding proposed in 2005 are estimated to protect at least two thirds of susceptible people, not all, and some people react to patterns that pass. The audit has no check for patterns, so every one needs a person's eye.

---

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