Figma to Code skill for Claude Code
Build what the designer meant, not just what they drew. Claude reads Figma variables, text styles and auto layout before measuring pixels, maps each value to the tokens and components already in your codebase, and translates auto layout settings literally into flex and grid. It sends handoff questions about missing states and breakpoints early, then verifies the build with screenshot overlays and lists every deviation.
- name
figma-to-code - size155 lines · ≈1,900 tokens
- files1
- licenseMIT
- updated
What Claude sees before loading it
This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.
description: Translates Figma designs into production code faithfully — reads variables and styles before pixels, maps auto layout to flexbox and grid, converts Figma typography, effects, and strokes to CSS, reuses existing components and tokens, asks the right handoff questions, and verifies with screenshot overlays. Use when implementing a Figma frame, file, or Dev Mode link, converting a mockup screenshot to components, or when the built UI does not match the design. Try asking
- Implement this Figma frame using our existing components and tokens
- The pricing page doesn't match the design. Compare it to the Figma and fix the differences
- Convert these Figma auto layout specs into Tailwind classes
Use it when
- Implementing a Figma frame, file, or Dev Mode link
- Building UI from a mockup screenshot
- The built UI drifts from the approved design
- Mapping Figma variables to code tokens
Skip it when
- There is no design and you need to create one, use landing-page-design or dashboard-ui instead
- You are setting up the token pipeline itself, use design-system-tokens instead
How to check the result
A screenshot at the designed frame width overlaid on the Figma export lines up within one to two pixels, and the diff introduces no raw hex or off-scale pixel values.
The common mistake it prevents
Hard-coding the 1440 pixel frame width and fixed text heights, which matches the mockup exactly and breaks as soon as content or viewport changes.
An implementation is done when it matches the design at the designed widths within 1–2px, uses the project’s existing tokens and components instead of new magic numbers, behaves sensibly at widths the designer did not draw, and every ambiguity was resolved by a question rather than a guess.
Ground rules
- Read structure before pixels: variables, text styles, components, and auto layout tell you intent; absolute coordinates do not.
- Map to existing tokens and components first. A Figma value that is 1px off a token is almost always meant to be the token; confirm if it repeats.
- Auto layout is a flexbox spec. Translate it literally before “improving” it.
- Never hard-code the frame width. A 1440px frame describes one breakpoint, not a fixed layout.
- Ask, do not invent, for missing states (hover, focus, error, loading, empty), missing breakpoints, and real content lengths.
Workflow
- [ ] 1. Gather: frame links, Dev Mode access, variables/styles, prototype notes
- [ ] 2. Inventory components and tokens; map to the codebase
- [ ] 3. List open questions and send them before building edge cases
- [ ] 4. Build structure (semantic HTML) and layout from auto layout
- [ ] 5. Apply tokens: type, color, spacing, radius, effects
- [ ] 6. Add states, responsiveness, and real content
- [ ] 7. Verify with overlay/screenshot comparison and accessibility checks
1. Gather
- Use Dev Mode (or the Inspect panel) for exact values, variable names, and exports.
- If a Figma MCP server is connected, pull the selected frame’s design context, variables, and a screenshot through it instead of guessing from an image; treat the generated code as a starting point and remap it to project components and tokens.
- From screenshots only: state that measurements are estimates and confirm key values.
2. Map to the codebase
| Figma | Code |
|---|---|
Variable color/text/muted | Existing token --text-muted (create a mapping table if names differ) |
Text style Heading/H2 | Typography component or class (<h2 class="text-2xl">) |
Component instance Button / Primary / md | Existing <Button variant="primary" size="md"> |
| Detached instance or local styles | Flag to designer; likely drift |
| Raw hex not bound to a variable | Snap to nearest token; ask if it differs by more than a step |
# find whether a component already exists before building one
grep -rniE 'export (function|const) (Button|Badge|Avatar|Tabs)' src/components | head
3. Handoff questions (send early)
- Which breakpoints exist, and what happens between them?
- Max content width? Does the background go full-bleed?
- Hover, focus, active, disabled, loading, error, empty states for each interactive part?
- Longest realistic strings (names, titles, translations; German runs ~30% longer)?
- Truncate, wrap, or clamp lines for overflowing text?
- Which images are content (need alt text) vs. decorative? Source of real images?
- Motion: any transitions specified? Duration and easing?
- Are off-token values intentional?
4. Auto layout → CSS
| Figma auto layout | CSS |
|---|---|
| Horizontal / Vertical | display:flex; flex-direction: row / column |
| Wrap | flex-wrap: wrap plus row-gap from “vertical gap” |
| Grid auto layout | display:grid; grid-template-columns: … |
| Gap (spacing between items) | gap |
| Spacing “Auto” | justify-content: space-between |
| Padding | padding (check per-side values) |
| Alignment (9-point) | justify-content (main axis) + align-items (cross axis) |
| Child: Hug contents | flex: none / width: fit-content |
| Child: Fill container (main axis) | flex: 1 1 0; min-width: 0 |
| Child: Fill container (cross axis) | align-self: stretch |
| Child: Fixed width | width: Npx — prefer max-width or a token unless truly fixed (icons, avatars) |
| Min / max width | min-width / max-width |
| Absolute position inside auto layout | position: absolute within a position: relative parent |
| Clip content | overflow: hidden (or overflow: clip) |
| Frames without auto layout + constraints | Read constraints as responsive intent (left+right = stretch, center = centered) |
5. Property conversions
| Figma | CSS |
|---|---|
| Font size 18, line height 28px | font-size: 1.125rem; line-height: 1.556 (28 / 18, unitless) |
| Line height 150% | line-height: 1.5 |
| Line height Auto | line-height: normal or the type token; confirm |
| Letter spacing -2% | letter-spacing: -0.02em |
| Letter spacing in px | divide by font size → em |
| Drop shadow X 0 Y 4 Blur 12 Spread 0 #000 10% | box-shadow: 0 4px 12px 0 rgb(0 0 0 / 0.1) |
| Inner shadow | box-shadow: inset … |
| Stroke Inside 1px | border: 1px solid with box-sizing: border-box |
| Stroke Outside | outline or box-shadow: 0 0 0 1px (no layout shift) |
| Stroke Center | border; half-pixel differences are expected |
| Layer blur / Background blur | filter: blur() / backdrop-filter: blur(); tune visually, values do not map 1:1 |
| Corner smoothing (iOS squircle) | Not in CSS; use standard border-radius and accept the difference |
| Rotation, flips | transform |
| Blend modes | mix-blend-mode (test performance) |
| Text “Truncate” | overflow:hidden; text-overflow:ellipsis; white-space:nowrap or line-clamp |
Exports: icons as SVG (see svg-icons), photos as 2× source then served as AVIF/WebP
with srcset (see image-optimization). Never export text as images.
6. States and responsiveness
- Build each interactive state, including
:focus-visible(often missing from designs: use a 2px ring in the accent with 2px offset, 3:1 contrast). - Test widths between and beyond designed frames (320, 768, 1024, 1920).
- Replace placeholder copy with the longest realistic strings and check wrapping.
Gotchas
- Figma “Fill” children without
min-width: 0overflow in CSS when content is long. - Designers often place text in fixed-height frames; in code, let height be intrinsic or text will clip when content changes.
- Figma renders fonts slightly differently (especially on Windows browsers); compare layout and spacing, not antialiasing.
- Grouped layers named “Rectangle 42” usually mean a background or card; implement as a CSS background on the container, not an extra div.
- Hidden layers and unused variants appear in exports and generated code; ignore them.
- Generated code from plugins or MCP uses absolute values and divs; refactor into
semantic elements (
button,nav,ul, headings) before shipping.
Verification
- Overlay: take a screenshot at the frame width (e.g. Playwright
page.setViewportSize({ width: 1440, height: 900 })) and compare against the Figma export at 50% opacity; spacing and alignment within 1–2px. - Token check: no raw hex or off-scale px values introduced
(
git diff | grep -E '#[0-9a-fA-F]{3,6}|[0-9]+px'). - Every state from the design (and the ones you asked for) is reachable and visible.
- Keyboard and screen reader sanity: tab order follows visual order; images have alt.
- Report deviations explicitly.
Output contract
## Implemented: <frame name / link>
Reused components: Button, Card, Avatar. New components: PlanToggle (reason: no equivalent)
Token mapping: Figma color/brand/600 → --accent; spacing 20 → --space-5
Deviations: card radius 14 → 12 (token); shadow simplified to elevation-2
Open questions sent: hover state for plan cards; behavior below 768px
Verified: overlay at 1440 and 390, states, keyboard About this skill
Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.