{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"css-scroll-driven-animation","type":"registry:block","title":"CSS scroll-driven animation","description":"\"cheap reveals via 85\" — scroll-linked animation with no JS at all. The free-performance version of 14.","author":"Motion Menu","categories":["role-content","platform-native","css"],"dependencies":[],"registryDependencies":[],"meta":{"number":"85","slug":"css-scroll-driven-animation","framework":"react","docs":"https://motion-menu-two.vercel.app/p/css-scroll-driven-animation.md"},"files":[{"path":"motion-menu/css-scroll-driven-animation.html","type":"registry:file","target":"motion-menu/css-scroll-driven-animation.html","content":"<article class=\"card\">\n        <header><span class=\"num\">85</span><h3>CSS scroll-driven animation</h3><div class=\"tags\"><i>pure CSS</i></div><a class=\"format-action\" data-format-link data-pattern-slug=\"css-scroll-driven-animation\" href=\"/r/css-scroll-driven-animation.json?framework=react\" title=\"Open the React registry output\">React ↗</a></header>\n        <div class=\"demo\" style=\"overflow-y:auto;\" data-lenis-prevent>\n          <span class=\"support-badge\" id=\"sup-85\"></span>\n          <div class=\"sda-list\" style=\"padding: 6rem 0;\">\n            <div class=\"sda-item\">scroll this little panel —</div>\n            <div class=\"sda-item\">each row animates in…</div>\n            <div class=\"sda-item\">…driven by CSS alone.</div>\n            <div class=\"sda-item\">zero JavaScript. zero GSAP.</div>\n            <div class=\"sda-item\">animation-timeline: view()</div>\n          </div>\n        </div>\n        <p class=\"order\">Say: <b>\"cheap reveals via 85\"</b> — scroll-linked animation with no JS at all. The free-performance version of 14.</p>\n      </article>"},{"path":"motion-menu/css-scroll-driven-animation.css","type":"registry:file","target":"motion-menu/css-scroll-driven-animation.css","content":".card {\n    border: 1px solid var(--line); border-radius: 14px; background: var(--card);\n    overflow: hidden; display: flex; flex-direction: column;\n  }\n\n.card > header { display: flex; align-items: baseline; gap: .8rem; padding: 1.1rem 1.2rem .9rem; border-bottom: 1px solid var(--line); }\n\n.card .num { font-family: var(--mono); color: var(--acc); font-size: 1.05rem; }\n\n.card h3 { font-size: 1.02rem; font-weight: 600; letter-spacing: -0.01em; flex: 1; }\n\n.tags { display: flex; gap: .35rem; }\n\n.tags i {\n    font: 400 .62rem/1 var(--mono); font-style: normal; color: var(--dim);\n    border: 1px solid var(--line); border-radius: 99px; padding: .28em .6em; white-space: nowrap;\n  }\n\n.demo {\n    min-height: 250px; position: relative; display: flex; align-items: center; justify-content: center;\n    background: var(--bg2); overflow: hidden; flex: 1;\n  }\n\n.order { padding: .85rem 1.2rem; font-family: var(--mono); font-size: .72rem; color: var(--dim); border-top: 1px solid var(--line); }\n\n.order b { color: var(--txt); font-weight: 500; }\n\n.demo .btn.corner { position: absolute; top: 12px; right: 12px; padding: .55em 1em; font-size: .68rem; z-index: 5; }\n\n.ai-card .num { color: var(--acc2) !important; }\n\n/* ---------- Section L · platform natives ---------- */\n  .support-badge { position: absolute; top: 12px; left: 14px; font: 400 .6rem var(--mono); border-radius: 99px; padding: .3em .7em; z-index: 4; }\n\n.support-badge.yes { color: var(--acc); border: 1px solid rgba(183,255,46,.4); }\n\n.support-badge.no { color: #ff8f6e; border: 1px solid rgba(255,143,110,.4); }\n\n.sda-list { display: flex; flex-direction: column; gap: .8rem; width: 76%; }\n\n.sda-item { border: 1px solid var(--line); border-radius: 8px; padding: .85rem 1.1rem; font: 400 .78rem var(--mono); color: var(--dim); background: rgba(255,255,255,.02); }\n\n.sda-item { animation: sda-in linear both; animation-timeline: view(); animation-range: entry 0% entry 80%; }\n\n.demo:has(.hascheck input:checked) .hasbtn { border-color: var(--acc); color: var(--acc); pointer-events: auto; opacity: 1; }\n\n@keyframes sda-in { from { opacity: 0; transform: translateY(34px) scale(.96); } }"},{"path":"components/motion-menu/css-scroll-driven-animation.tsx","type":"registry:component","content":"// @ts-nocheck — generated wrapper; inlined pattern JS is imperative DOM code, not authored TS.\n\"use client\";\n// CSS scroll-driven animation — Motion Menu\nimport { useEffect, useRef } from \"react\";\n\nconst MARKUP = \"<article class=\\\"card\\\">\\n        <header><span class=\\\"num\\\">85</span><h3>CSS scroll-driven animation</h3><div class=\\\"tags\\\"><i>pure CSS</i></div><a class=\\\"format-action\\\" data-format-link data-pattern-slug=\\\"css-scroll-driven-animation\\\" href=\\\"/r/css-scroll-driven-animation.json?framework=react\\\" title=\\\"Open the React registry output\\\">React \\u2197</a></header>\\n        <div class=\\\"demo\\\" style=\\\"overflow-y:auto;\\\" data-lenis-prevent>\\n          <span class=\\\"support-badge\\\" id=\\\"sup-85\\\"></span>\\n          <div class=\\\"sda-list\\\" style=\\\"padding: 6rem 0;\\\">\\n            <div class=\\\"sda-item\\\">scroll this little panel \\u2014</div>\\n            <div class=\\\"sda-item\\\">each row animates in\\u2026</div>\\n            <div class=\\\"sda-item\\\">\\u2026driven by CSS alone.</div>\\n            <div class=\\\"sda-item\\\">zero JavaScript. zero GSAP.</div>\\n            <div class=\\\"sda-item\\\">animation-timeline: view()</div>\\n          </div>\\n        </div>\\n        <p class=\\\"order\\\">Say: <b>\\\"cheap reveals via 85\\\"</b> \\u2014 scroll-linked animation with no JS at all. The free-performance version of 14.</p>\\n      </article>\";\n\nexport function CssScrollDrivenAnimation() {\n  const hostRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const host = hostRef.current;\n    if (!host) return;\n    const $ = (s: string) => host.querySelector(s) as HTMLElement | null;\n    let disposed = false;\n    const cleanup: Array<() => void> = [];\n\n    (async () => {\n      if (disposed) return;\n      try {\n        /* ---- 85 · CSS scroll-driven animation ---- */\n        setSupport('sup-85', CSS.supports('animation-timeline: view()'));\n      } catch (err: any) {\n        console.warn(\"[motion-menu] css-scroll-driven-animation failed to start:\", err);\n      }\n    })();\n\n    return () => {\n      disposed = true;\n      cleanup.forEach((fn) => { try { fn(); } catch (_) {} });\n    };\n  }, []);\n\n  return <div ref={hostRef} dangerouslySetInnerHTML={{ __html: MARKUP }} />;\n}\n\nexport default CssScrollDrivenAnimation;\n"}]}