Skill / CSS-first
CSS-first motion & sizing
Drive sizing, enter/exit motion, and scroll effects from CSS and native attributes — token-driven and progressively enhanced — instead of measuring and animating values in JavaScript.
Goal
Move sizing and motion off the main thread and out of effects, keeping every duration on the theme's motion tokens and every cutting-edge property behind a working fallback.
Reach for modern CSS — relational selectors, container and style queries, and native platform elements — before React state, effects, and event handlers, so interaction, sizing, and motion stay declarative, server-rendered, and JavaScript-free.
Checks
1Auto-grow inputs with `field-sizing: content` (Tailwind `field-sizing-content`, bounded by `min-h`/`max-h`) instead of a ref copying `scrollHeight` back into a height; fade scroll edges with a `mask-image` gradient driven by overflow attributes, not a scroll listener.
2Animate enter/exit with `@starting-style` + `transition-behavior: allow-discrete` (Tailwind `starting:` + `transition-discrete`) rather than mount/unmount timers or an animation library, and keep every duration/easing on the theme's `--duration-*`/`--ease-*` tokens so the reduce-motion kill-switch flattens them.
3Animate to intrinsic size with the `grid-template-rows: 0fr → 1fr` collapse (widely supported) as the base, and progressively enhance to `interpolate-size: allow-keywords`/`calc-size(auto)` behind `@supports`, instead of measuring the panel and animating a pixel height.
4Guard Limited features — anchor positioning (`anchor()`/`position-try`), scroll-driven animations (`animation-timeline: scroll()`/`view()`), style queries, and `if()` — behind `@supports`, keeping the JS path (Floating UI, `IntersectionObserver`) as the fallback so an unsupported browser still gets a correct, static result.
Avoid
1Measuring `scrollHeight`/`getBoundingClientRect` on every keystroke, resize, or scroll to set a style a container query, `field-sizing`, or scroll-driven animation already reaches.
2JS enter/exit libraries for a fade or slide that `@starting-style` plus a token transition expresses in a few lines.
3Shipping an experimental CSS feature (anchor positioning, `if()`, `interpolate-size`, scroll-driven timelines) as a hard dependency with no `@supports` fallback, or hardcoding millisecond durations that bypass the motion tokens and the reduce-motion kill-switch.