Skip to content

devlog

Honoring reduced motion by freezing a carousel was the less accessible choice

2026-10-08

The phone front page held still under prefers-reduced-motion. That was defensible right up until the arrows came off it, and then it quietly was not.

The same report that found the bytes problem in the post above found this, and it is a cleaner thing to think about.

The phone front page turns through the places on its own. It honored prefers-reduced-motion: reduce by not turning at all. On the face of it that is correct. Content that changes by itself is motion, and the preference asks for less of it.

It is worth knowing how many people are actually in that branch, because I had assumed very few. A phone picks that preference up from iOS Reduce Motion, and on Android from battery saver, which switches animations off. Neither of those is a setting somebody turns on because they are thinking about vestibular triggers on a marketing page. The visitor who reported this had it on and did not know it.

Freezing used to be a fine answer because there were arrows. A visitor who had asked for stillness lost the automatic turn and kept the manual one, and all eleven places were still two presses away.

Then the arrows came off, for reasons that had nothing to do with accessibility: the photograph fills the screen and is already a swipe target, and two circles of chrome laid over it were doing a worse version of what a thumb across the frame does. That is a defensible change on its own. What it did to the reduced-motion branch is the part I nearly shipped without noticing. A reduced-motion visitor now got one place out of eleven, and no control at all except a gesture that nothing on the screen advertises. The preference was being honored into a dead end.

So the stage turns for everybody now, and the preference is honored where it means something instead: the bar that fills during the hold stops animating and sits full, as a plain mark of where you are in the set. The swap between photographs stays a crossfade, because an opacity ramp is what that preference asks motion to be replaced by rather than a thing it asks to be removed. The triggers it exists for are parallax, spin and large translation, not a dissolve.

The shape of the mistake generalises, and it is the reason I am writing it up rather than just fixing it. A preference is honored by its effect on the person, not by the literal removal of the thing it names. The question to ask is not "have I disabled the motion", it is "what is this visitor left with". The answer to that changed under me when an unrelated control was deleted, and nothing in the codebase connected the two. The reduced-motion branch had no test, so nothing failed.

It has one now, and it fails without the fix. While I was in there I also found that the site’s accessibility page describes its reduced-motion behaviour as disabling the home hero’s Ken Burns drift. That hero deliberately has no Ken Burns, because a slow scale on a flat image is faked depth and that is the wrong lie to tell on a page whose claim is real geometry. So the published promise has been describing something that does not exist. That is its own pass, and I have not made it yet.

Live on the site.