v2.7.1framer.overridelive
scroll-variant.ts — framecraftTypeScript

Framer, unpacked.

Line-by-line dissections of Framer overrides, CMS architecture, and motion systems. Built for developers billing production sites.

scroll
01 // Overrides34 tutorials~8 min

The layer between design and logic.

#scroll#variants#state#hooks
problem

Scroll Variants stop working the moment you add a Code Override to the same component. Here's why — and how to architect around it.

solution

Overrides and Scroll Variants compete for the same variant state. The fix isn't removing one — it's sequencing them correctly with a shared ref.

overrides.ts — preview
1// Problem: override clears scroll variant state
2export function HoverCard(): Override {
3 return {
4 onHoverStart: () => setVariant("hovered")
5 // ⚠ this resets on scroll — see fix →
6 }
7}
8// Fix: lift variant to shared atom
9const variantAtom = atom<string>("default")
10export function ScrollVariantFix(): Override {
11 const [variant, setVariant] = useAtom(variantAtom)
12 more lines — Pro only
unlock →
02 // CMS28 tutorials~11 min

Content as data. Data as components.

#cms#collections#plugin-api#rich-text
problem

CMS fields show 'Missing' on your component even though the collection exists. The connection breaks silently — no error, just blank.

solution

The component must live on a CMS Detail page bound to the correct collection. Plain text and Rich Text are different field types — mixing them is the #1 silent failure.

cms.ts — preview
1// Framer CMS collection schema
2type BlogPost = {
3 title: string // plain text
4 body: RichText // ⚠ NOT string
5 slug: string
6 publishedAt: Date
7}
8// Plugin: managed collection with selective editability
9await framer.createCollection({
10 fields: [
11 { name: "title", userEditable: false },
12 more lines — Pro only
unlock →
03 // Components41 tutorials~14 min

React on the canvas. No compromises.

#react#property-controls#auto-sizing#canvas
problem

Your Code Component renders in the editor but breaks on publish. Property Controls don't expose the right props. Auto-sizing collapses to zero.

solution

Code Components are React 18 components — they run in three contexts simultaneously. Each context has constraints. Here's how to write for all three.

components.ts — preview
1import { addPropertyControls, ControlType } from "framer"
2 
3export default function Card({ label, color }) {
4 return <div style={{ background: color }}>{label}</div>
5}
6 
7addPropertyControls(Card, {
8 label: { type: ControlType.String, title: "Label" },
9 color: { type: ControlType.Color, title: "Color" }
10})
11// Auto-sizing: add to framer.json
12 more lines — Pro only
unlock →
04 // Motion22 tutorials~9 min

Scroll transforms that actually ship.

#scroll-transform#sticky#useTransform#viewport
problem

Sticky scroll animations stutter when the trigger frame moves through the viewport. The sticky layer shifts instead of staying locked.

solution

The sticky layer needs a separate z-index context from the trigger frames. Scroll transforms and Scroll Variants operate on different timing — here's how to sync them.

motion.ts — preview
1// Sticky layer + scroll transform sync
2const y = useTransform(scrollYProgress, [
3 0, 0.5, 1
4], ["0px", "-80px", "0px"])
5 
6const opacity = useTransform(scrollYProgress, [0, 0.2, 0.8, 1], [0, 1, 1, 0])
7// trigger: 'center' not 'top' for viewport sync
8return (
9 <motion.div style={{ position: "sticky", top: 0, y, opacity }}>
10 more lines — Pro only
unlock →
05 // Shipping17 tutorials~12 min

From Figma handoff to deployed CMS in one session.

#figma#handoff#cms-binding#workflow
problem

Figma-to-Framer handoffs break when the designer's component structure doesn't match Framer's CMS binding model. You rebuild instead of import.

solution

Start the component design on a CMS Detail page — not a blank canvas. Framer auto-wires the bindings. Then convert to a reusable component and the connections persist.

shipping.ts — preview
1// CMS Detail page → reusable component workflow
2// Step 1: design on /blog/[slug] (CMS detail page)
3// Step 2: bind text layers to CMS fields
4// Step 3: select all → Create Component
5// Framer preserves CMS bindings automatically ✓
6 
7// Result: reusable component with live CMS data
8// Dynamic linking pattern:
9const BlogCard = withCMS(Card, {
10 collection: "blog-posts",
11 fields: { title: "title", image: "coverImage" }
12 more lines — Pro only
unlock →
framecraftaccess control

Unlock Full Tutorials

You've seen the problem. You've seen the first few lines of the fix. Pro gives you the complete override, the source file, and the explanation of why it works.

3 tutorials per month
Snippet copy access
Preview code blocks
Community forum

No credit card. 3 full tutorials every month, free forever.