Skip to content
Get started

Motion

Three presets, and the rule that reduced motion always wins.

site.yaml
motion: subtle     # none | subtle | expressive

Pages and individual sections may override it:

pages.yaml
- name: launch
  motion: expressive
  sections:
    - launch/hero
    - { section: launch/features, motion: none }

The presets

Nothing animates. Content renders visible on the first paint. Choose this for a documentation-only site, or where motion is a distraction.

Two rules the engine keeps

Only transform and opacity animate. Never width, height, margin or anything else that affects layout — so an entrance animation cannot contribute to layout shift. A test asserts this rather than trusting it.

prefers-reduced-motion beats configuration. It is not one of the three presets and not a setting; a visitor who has asked their system for less motion gets none regardless of what the site says, including for the scroll-linked effects under expressive.

Video

A media-panel video is muted, looping and playsinline, and autoplay is decided in JavaScript rather than by the autoplay attribute — the attribute would have it moving before any code could stop it. Under reduced motion the poster stands in, which is what the still frame is for.

video-embed never loads anything until the visitor presses play. A poster image and a play button is all that ships.

Testing motion

The e2e suite covers this directly: that reveals fire on scroll, that nothing animates a layout-affecting property, and that under reduced motion every section renders visible with no animation at all.

If you are writing tests against a Zellij site and measuring element positions, emulate reduced motion first. Measuring mid-reveal reads a position offset by however far through the translate it happens to be — that is not a flake, it is an animation doing its job.