The Anemoi
One wind over the whole country. Everything in it leans the same way at the same moment, which is how you know it is one wind and not four.
The pair to sky, and the same argument: components that each read the clock for themselves drift apart, and components that read one published hour agree. Motion is the other thing worth agreeing about, and nothing published it — six components here bound their own scroll listener and each derived its own idea of progress. It publishes two things. Position, which several components already computed separately and identically. And rate — how fast the page is being thrown and which way — which no component could see at all, because measuring it means keeping frame history nobody was keeping. Rate is the recognisable property of the sites this is aimed at: things that lag, skew and settle according to how hard you pushed. It draws nothing, takes no space, and it is never required — a component that finds a wind reads from it and a component that does not keeps its own listener and behaves exactly as before.
One wind, and everything in it leans together.
Integration
<link rel="stylesheet" href="anthemion.css">
<script type="module" src="anthemion.js"></script>
<anthemion-anemos settle="25"></anthemion-anemos>Slot
The site shell, around everything. Anything that reads scroll, rate or direction reads it from here rather than measuring its own.
Custom properties
--anemos-scroll--anemos-velocity--anemos-gust--anemos-direction--anemos-pointer-x--anemos-pointer-y
Budget
- One per document, in the shell. Two winds is two answers to the same question, and the components below would split between them.
- Never nested. A wind inside a wind is the bug it exists to prevent.
- Reduced motion pins the rate to zero and leaves position alone. Lay out from `--anemos-scroll`, but never make anything a reader must see depend on `--anemos-velocity` — under Reduce Motion that value is always 0 and always will be.
- Leave `pointer` off unless something on the page genuinely answers the cursor. It costs a frame loop for as long as the pointer is moving, and it binds nothing on a touch device or under reduced motion in any case.
- It publishes and nothing else. Never give it a background, a border, a role or a size — it is `display: contents` precisely so that wrapping the document changes no layout.
- Every consumer reads through a fallback — `var(--anemos-velocity, 0)`. Without JavaScript nothing is published, and a page that collapses without it has broken the library's own no-JS guarantee.
Restraint is the aesthetic, and it does not survive being applied generously. These limits are the specification, not advice.