Pick a crate of lager, shandy or cider and we will knock 50% off a box of crisps. Take the crate
Motion

Shipped on day one, never as a retrofit.

This site has a scroll-scrubbed frame sequence, a pinned split-scroll, a page transition plane, a letter-by-letter chapter card and a drifting marquee. Under prefers-reduced-motion every one of them becomes a 120 millisecond cross-fade, and the identity survives.

The argument

Why it is built this way round.

  1. Reduced motion is not a downgrade path

    If the reduced-motion version is built afterwards, it is always a subtraction: things stop appearing, layouts collapse, and content that only existed inside an animation goes missing.

    Built first, it is the base case. The motion is the enhancement, and removing an enhancement cannot break anything.

    The still version is the design. The moving version is a performance of it.

  2. Nothing that matters lives inside an animation

    Every scrubbed frame has a first frame that stands alone. Every pinned sequence is a legible stack of blocks when it is not pinned. Every staggered reveal starts at full opacity when the stagger is off.

    That is a content rule rather than a CSS rule, and it is the one that actually does the work.

  3. The chapter card still stamps, it simply does not perform

    The animatic transition is 1200 milliseconds with two deliberate stutter holds in it, and those holds are the whole difference between an animatic and a corporate scroll library.

    Under reduced motion it is a 120 millisecond cross-fade. The number still appears, the gerund still appears, the beast still appears. Nobody is told less.

  4. And the global rule is a floor, not the whole answer

    The stylesheet does clamp every animation and transition to 0.01ms under the media query, which catches anything a component author forgot.

    But a blanket clamp on its own produces things that snap rather than things that were designed to be still, which is why each of the five big motion pieces has its own named reduced state.

Eight pieces

What each piece degrades to.

MotionNormallyUnder reduced motion
The chapter card 1200ms animatic with two stutter holds 120ms cross-fade. Everything still appears
Scroll-scrubbed frames A frame sequence driven by scroll position A single frame and a caption. Which is a storyboard, which is honest
Pinned split-scroll The plate holds while the copy walks past An ordinary stack of blocks, in order
The page transition plane A skewed wipe across the viewport No wipe. The next page is simply there
The marquee A slow horizontal drift Static, wrapped, and readable
Staggered reveals 40ms per item, translated up Present at full opacity, no transform
Parallax layers Offset against scroll Not offset
Odometers Counting up on entry The final number, immediately
The implementation

How it is enforced.

The global floor

Media query
@media (prefers-reduced-motion: reduce)
Animation duration
Clamped to 0.01ms, with !important
Iteration count
Clamped to 1
Transition duration
Clamped to 0.01ms
scroll-behavior
auto, so anchor jumps do not scroll

The named replacements

Chapter card
A 120ms opacity fade, applied to all four of its parts
Scrub sequences
Runtime does not attach; the first frame stays
Split-scroll
Runtime does not pin; the steps render as a stack
Reveal helpers
Opacity 1 and transform none, forced

Also capped, for everybody

Split-scroll sections
Two per page maximumMore than that and the site becomes a showreel rather than a place to buy jam
Marquee
One per page
Autoplaying video
None anywhere on the site
Progressive enhancement

The bit that is easy to get wrong.

A great many sites implement prefers-reduced-motion by disabling their scroll library and stopping there. What that produces is a page where half the content is still sitting at opacity zero waiting for a reveal that will never fire.

The fix is unglamorous: every element that a runtime will animate has to be visible and correctly positioned before that runtime touches it, and the runtime hides it only after confirming it is going to animate it.

It means the page flashes fully-formed for a frame on a fast connection with motion enabled, which is a cosmetic cost. The alternative is a blank page for anybody whose JavaScript failed, which is not cosmetic at all.

And the same applies to the seasonal layer

None of the live inputs animate anything. The palette swap happens server-side before first paint, the ticker does not scroll under reduced motion, and no value on this site ever counts up, flashes or pulses to draw attention to itself.

How Seasoning works

Reduced motion, in four lines

Day one

Not a retrofit.

A storyboard

What a scrub sequence becomes.

Nothing hidden

No content lives only inside an animation.

Identity survives

It appears. It simply does not perform.

The full accessibility position.

Contrast, focus, targets, labelling and what this build knows it has not done.

Next along the route

The weather

Carry on
Basket Book the pub Plot a field Join the list Bother us

Snooping, briefly.

We use a small number of cookies to keep your basket upright and to work out which pages people actually read. We do not sell anything about you to anyone, because that would be a rotten way to behave.

Read the detail