Skip to content

Rule · Lint

Base rule hides an element; only an @supports (animation-timeline: …) block undoes it

lint/scroll-timeline-no-fallbackwarnvoid lintupdated

Why it matters

animation-timeline: view()/scroll(), view-timeline and animation-range have no fallback: a browser that doesn't implement them (Firefox, at every version through 151) evaluates the @supports condition as false and drops the whole block, keyframes included. If the resting rule for the same selector sets opacity: 0, visibility: hidden, a zero scale or a large translate and nothing outside that @supports block ever undoes it, the element is invisible forever in that browser — not degraded, gone.

How to fix it

Keyframes own the from-state: keep the resting rule (outside @supports) as the finished, visible state and move the hidden value into @keyframes, the way @utility reveal in packages/tokens/css/base.css does it. See skills/motion/references/fallbacks.md.

Example

css
/* flagged: base rule hides it, only @supports undoes it */
.card { opacity: 0; }
@supports (animation-timeline: view()) {
  .card { animation: reveal linear both; animation-timeline: view(); }
}

/* fixed: resting state is visible; the keyframe owns opacity: 0 */
@supports (animation-timeline: view()) {
  .card { animation: reveal linear both; animation-timeline: view(); }
}
@keyframes reveal { from { opacity: 0; } }

References

void lint reports 67 rules in this category. Static source checks with no browser: Tailwind v4 silent failures, Next.js 16 API traps, React render-body bugs, accessibility markup, SEO files and motion hygiene.