Figma Auto Layout to Flutter: the Row, Column and Expanded cheat sheet
Every Figma Auto Layout setting has a direct Flutter equivalent. Here is the full mapping — direction, gap, padding, alignment, Hug / Fill / Fixed, wrap and absolute position — with the code, and the mistakes that cause the famous RenderFlex overflowed error.
The short version
- Horizontal Auto Layout →
Row. Vertical →Column. - Gap between items →
spacing:on the Row/Column (Flutter 3.27+) or aSizedBoxbetween children. - Padding →
Paddingor aContainer'spadding:. - Fill container →
Expandedalong the parent's axis;CrossAxisAlignment.stretchacross it. - Hug contents →
mainAxisSize: MainAxisSize.min. - Fixed →
SizedBox(width: …, height: …).
Full mapping table
| Figma Auto Layout | Flutter |
|---|---|
| Direction: horizontal | Row |
| Direction: vertical | Column |
| Direction: wrap | Wrap(spacing: gap, runSpacing: rowGap) |
| Gap between items (number) | spacing: 12 or SizedBox(width/height: 12) |
| Gap: Auto (space between) | mainAxisAlignment: MainAxisAlignment.spaceBetween |
| Padding | Padding(padding: EdgeInsets.fromLTRB(l, t, r, b)) |
| Alignment along the direction | mainAxisAlignment: start / center / end |
| Alignment across the direction | crossAxisAlignment: start / center / end |
| Child width/height: Fill container (along axis) | wrap the child in Expanded (or Flexible) |
| Child Fill container (across axis) | crossAxisAlignment: CrossAxisAlignment.stretch on the parent |
| Frame Hug contents (along axis) | mainAxisSize: MainAxisSize.min |
| Fixed width / height | SizedBox(width: w, height: h) |
| Min / max width | ConstrainedBox(constraints: BoxConstraints(minWidth: …, maxWidth: …)) |
| Absolute position (child ignores Auto Layout) | Stack + Positioned |
| Clip content | ClipRect / clipBehavior: Clip.hardEdge |
| Text: Auto width | plain Text |
| Text: Fixed width + truncate | Text(…, maxLines: 1, overflow: TextOverflow.ellipsis) inside Expanded or a fixed SizedBox |
| Content taller than the screen | SingleChildScrollView or ListView |
mainAxisAlignment. In a Column it flips — Figma's vertical alignment becomes mainAxisAlignment.Worked example: a list row
A classic Figma component: horizontal Auto Layout, 16 padding, 12 gap, a fixed 40×40 avatar, a text block set to Fill container, and a chevron icon.
Container(
padding: const EdgeInsets.all(16), // Figma padding
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Row( // horizontal Auto Layout
spacing: 12, // Figma gap
children: [
const SizedBox( // Fixed 40×40
width: 40, height: 40,
child: CircleAvatar(),
),
Expanded( // Fill container
child: Column( // vertical Auto Layout
mainAxisSize: MainAxisSize.min, // Hug contents
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4,
children: const [
Text('Priya Sharma'),
Text(
'Product designer, Bengaluru',
maxLines: 1,
overflow: TextOverflow.ellipsis, // Truncate text
),
],
),
),
const Icon(Icons.chevron_right),
],
),
)
Resize the screen and it behaves like the Figma frame does when you drag its edge: the text column grows and shrinks, the avatar and icon stay fixed, and long text truncates instead of overflowing.
Four mistakes behind most Flutter layout errors
1. Fill container without Expanded
A long Text in a Row has no width limit, so it pushes past the edge: A RenderFlex overflowed by 42 pixels on the right. In Figma that text was set to Fill — in Flutter it needs Expanded.
2. Expanded inside a scroll view
A scroll view gives its child infinite height, and "fill infinite space" has no answer — Flutter throws RenderFlex children have non-zero flex but incoming height constraints are unbounded. Fill inside a scrolling frame usually means "Hug" in Flutter.
3. Space-between in a Hug parent
spaceBetween distributes leftover space. If the Row is MainAxisSize.min there is none, so nothing moves. Figma behaves the same way — Auto gap only works when the frame is Fixed or Fill.
4. Rebuilding everything with Stack + Positioned
Copying x/y coordinates out of Figma looks pixel-perfect on one phone and breaks on every other. Keep Stack for real overlaps — a badge on an avatar, a floating button — and use Row/Column for everything else.
What if the design has no Auto Layout?
Most real Figma files are a mix: some frames use Auto Layout, many are just positioned layers. That is where hand-conversion takes longest, and where many code generators fall back to absolute positioning.
Desynq is a Figma to Flutter code generator that does not need Auto Layout. Its engine reads the positions of the layers and rebuilds the structure with fixed rules: siblings that stack vertically become a Column, items side by side become a Row, the exact gaps become spacing, and only genuinely overlapping layers become a Stack. It is deterministic — the same frame always produces the same code — so you can review it like any other diff.
Free Figma plugin · live Flutter preview · no credit card.
Get the Figma plugin →