--- name: hyperframes-css-animations description: CSS animation adapter patterns for HyperFrames. Use when authoring CSS keyframes, animation-delay based timing, animation-fill-mode, animation-play-state, or CSS-only motion that HyperFrames must seek deterministically during preview and rendering. --- # CSS Animations for HyperFrames HyperFrames can seek CSS keyframe animations through its `css` runtime adapter. Use this for simple repeated motifs, background motion, shimmer, glow, masks, and non-sequenced decoration. For scene choreography, GSAP is usually clearer. CSS animations work best when the motion belongs to one element and has a fixed duration. ## Contract - Put the animated element in the DOM before runtime initialization finishes. - Give timed elements a `data-start` value so local animation time matches the clip. - Use finite `animation-duration` and `animation-iteration-count` because the negative-delay fallback cannot represent unbounded duration in environments without WAAPI-backed CSS animations. - Prefer `animation-fill-mode: both` so seeked states hold before and after active motion. - Avoid wall-clock JavaScript, hover-triggered state, and class toggles that depend on user events. The adapter discovers elements with computed `animation-name`, seeks their browser `Animation` handles when available, and falls back to pausing with negative `animation-delay`. ## Basic Pattern ```html
``` ## Stagger Pattern Use CSS custom properties to avoid duplicating keyframes: ```html
``` ## Good Uses - Decorative loops with a known repeat count. - Mask, glow, shimmer, grain, and subtle parallax layers. - Simple one-element entrances where a full JS timeline would be excessive. ## Avoid - Infinite CSS animations unless you have verified the browser exposes seekable WAAPI-backed CSS animation handles. Prefer a finite iteration count covering the visible duration. If you do use `infinite`, add `data-duration` to the root element — see Composition Duration below. - Animating layout properties like `top`, `left`, `width`, or `height` when transforms work. - Relying on hover, focus, scroll, or media queries to trigger render-critical motion. - Changing animation classes after startup unless another deterministic timeline controls that change. ## Composition Duration The render engine needs to know the composition's total length. GSAP timelines report this automatically; CSS-only compositions have no timeline object, so the runtime infers duration from the longest running animation's computed end time (`animation-delay` + `animation-duration` × finite `animation-iteration-count`, per element with `data-start` added as an offset). `data-duration` on the root element is optional whenever every CSS animation on the page is finite — you don't need to add it just because the composition is CSS-driven. `animation-iteration-count: infinite` (or any unresolved/unbounded animation) has no finite end time, so it cannot be auto-inferred. If the composition's only animation is infinite, you **must** add `data-duration=""` to the root `[data-composition-id]` element with your intended total length — `npx hyperframes lint` errors on this case (`root_composition_missing_duration_source`) precisely because there is nothing for the runtime to infer. ```html
``` ## Validation After editing CSS animation compositions: ```bash npx hyperframes lint npx hyperframes check ``` ## Credits And References - HyperFrames adapter source: `packages/core/src/runtime/adapters/css.ts`. - Duration auto-inference: `packages/core/src/runtime/init.ts` (`resolveAdapterDurationFloorSeconds`), `getInferredDurationSeconds` in the adapter above. - MDN CSS animation documentation: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/animation - MDN `animation-fill-mode`: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode