Guide
Figma to Webflow: how to tell whether the build actually matches the design
A measured comparison beats eyeballing it. Here is what to read from both sides, in what order, and the two traps that make a correct build look wrong.
Published 15 September 2026
- 1. Compare numbers, not impressions
- 2. Two traps that will waste your afternoon
- 3. What to check, in order
- 4. Doing it automatically
- 5. After the handoff
Handing a Figma file to Webflow is where most of a design's precision goes missing,
and it goes missing quietly. Nobody ships a build that is obviously wrong. What ships
is a build where the h2 is 32px instead of 36px, the body line height is
1.4 instead of 1.2, and the muted grey is one step off — none of it visible side by
side, all of it visible in aggregate as a page that feels slightly cheaper than the
design did.
The usual QA for this is someone flipping between two tabs. That finds layout errors and reliably misses everything above, because the human eye is excellent at spotting a moved box and poor at spotting four pixels of type.
1. Compare numbers, not impressions
Both sides of the handoff can be read as data.
From Figma
The REST API returns the frame as a node tree. Every text node carries what was actually specified:
| What | Where |
|---|---|
| Font family, weight, size | style.fontFamily, style.fontWeight, style.fontSize |
| Line height | style.lineHeightPx |
| Letter spacing | style.letterSpacing |
| Colour | fills[0].color, as {r,g,b} in 0–1 — multiply by 255 |
| Box | absoluteBoundingBox |
Use lineHeightPx, not lineHeightPercent. The percentage is
relative to font metrics and does not compare cleanly against a browser's computed
value.
From the live page
getComputedStyle gives the same properties as the browser resolved them.
Set the viewport to the Figma frame's exact width first — 1440
for a 1440 frame. A 20px difference in viewport width changes where text wraps, and a
wrap difference cascades into every box measurement below it, so a mismatched viewport
produces a report full of differences that are all one difference.
Then match elements between the two and subtract.
2. Two traps that will waste your afternoon
Resized component instances lie about font size. If a text node lives
inside a component instance that has been resized — rather than inside
the main component — Figma's API can report style.fontSize from the
main component's original, not the visually scaled value you see on the canvas. The
practical rule: a font-size delta on one element whose siblings of the same visual
family are all correct is usually this artefact. A delta that repeats
identically across several elements is usually real. When in doubt, trust the repeating
one.
Pixel-perfect is unreachable, by construction. Figma and a browser are two different text rasterisers. Every glyph edge differs slightly even when the build is exactly right, so a Figma-versus-browser comparison needs a looser threshold than a browser-versus-browser one. Any tool that claims pixel-perfect Figma matching is either lying or thresholding silently and not telling you where.
3. What to check, in order
- Type scale. Every heading level and body size. The most common real error and the least visible.
- Line height and letter spacing. Where “feels cheaper” usually lives.
- Colour. Exact hex on text and backgrounds. Designers pick nine-step greys; builds land one step off constantly.
- Spacing. Section padding and gaps, at the frame's width.
- Wrap points. Whether headings break where the design breaks them.
Do this once at the frame width before checking anything responsive. A build that is wrong at 1440 is wrong everywhere, and fixing it at 1440 fixes most of the rest.
4. Doing it automatically
This is mechanical, which means it is worth automating, and it is what Pixelsitter does: give it a Figma frame link and a live URL, and it pulls both sides, matches elements, and reports the measured differences — “this heading is 32px and should be 36px” rather than “looks different”. It applies a deliberately looser threshold to design comparisons than to monitoring diffs, for the rasteriser reason above.
It is free for one site. If you would rather build it
yourself, everything needed is in this article: the Figma endpoint is
GET /v1/files/{key}/nodes?ids={node_id} with an
X-Figma-Token header, and the node id in a share URL uses a dash where the
API wants a colon (7344-6080 becomes 7344:6080). That single
detail is the most common reason a hand-built call returns a 404.
5. After the handoff
A build that matches on handoff day does not stay matching. The client gets CMS access, adds an entry longer than anything the design contained, and a card leaves its column. That is a different check — a diff against the last approved capture rather than against the design — and it is the subject of visual regression testing without CI. What breaks, specifically, is in the Webflow client handoff problem.
Related
Check a build against its Figma frame.
Paste a Figma link and a URL. You get measured differences, element by element, not a pixel percentage.
No credit card. One site free, for as long as you want it.