Framer Tips·OCT 28, 2026·19 MIN READ

Fixing Common Framer Layout Bugs: Prevent Squished Text and Uneven Columns

How to set text and column widths in Framer so buttons, badges, and cards behave on every screen.

08
Marcus Chen
Framer & Interactive Engineer
Featured template: Kyoto Atelier ↗
Summary

In Framer's scene-graph layout engine, a RichTextNode placed inside a vertical stack must use width: '1fr' and height: 'auto' to fill its container cleanly, whereas a RichTextNode inside a horizontal stack (such as a navbar or badge pill) must use width: 'auto' and height: 'auto'—unless paired with a single-Grow sibling—to prevent collapsing into a 1-character-per-line vertical column. For multi-column grids, setting gridRowHeightType: 'fit' on the parent FrameNode and width: '1fr', height: '100%' on child cards guarantees a 0px sibling height delta.

1. Inside Framer's Scene-Graph Engine: How FrameNode and RichTextNode Compute Intrinsic Size

Most designers interact with Framer exclusively through the visual mouse canvas, clicking between Fixed, Fill (1fr), and Fit Content (auto) dropdowns without realizing how those tokens map to the underlying scene-graph compiler. At Desk 08, I program and audit Framer scene graphs directly at the node tree level. Every layout container on a Framer page is a FrameNode operating either as a Stack (1D Flexbox along a vertical or horizontal axis) or a Grid (2D CSS Grid tracks), while every typography block is a RichTextNode.

Unlike a standard HTML div, a Framer RichTextNode calculates its intrinsic bounding box dynamically based on its parent FrameNode's primary axis direction and fractional unit (fr) distribution. When the parent axis and the child width token are aligned correctly, text reflows smoothly across every viewport width. When they conflict, Framer's layout solver resolves the fractional constraint down to a zero-pixel minimum width, producing the infamous vertical 1-character-per-line text tower that plagues amateur templates.

Understanding the mathematical relationship between stack direction, fractional distribution, and intrinsic content measurement is the foundation of Desk 08's Scene-Graph Sizing Laws. Once you lock these four invariants into your build pipeline, broken text columns and uneven card grids become structurally impossible.

2. Law #1: Why RichTextNode Demands 'width: 1fr' in Vertical Stacks

Let us start with the most common structural container on any B2B web page: a vertical stack (layout: 'stack', stackDirection: 'vertical') such as a hero copy column, a feature card body, or an article section. Inside a vertical stack, the primary layout axis runs top-to-bottom, while the cross-axis runs left-to-right. When you insert a RichTextNode—whether an H1 headline, a body paragraph, or a bulleted specification—into a vertical stack, its sizing properties must always be set to width: '1fr' (Fill) and height: 'auto' (Fit Content).

Why is width: '1fr' mandatory here? If you leave a RichTextNode set to width: 'auto' inside a vertical stack, the text node computes its intrinsic width as a single unwrapped line of characters. As soon as your sentence exceeds the pixel width of the parent card, the text shoots straight through the right border of the container instead of wrapping onto a second line.

Conversely, never set height: '1fr' on a RichTextNode inside a vertical stack. Forcing a text block to fill vertical fractional height decouples its bounding box from its actual line-height geometry, causing either clipped descenders on mobile screens or awkward dead air between paragraphs.

3. Law #2: The Horizontal Stack Trap and the 1-Character-Per-Line Vertical Collapse

Now watch what happens when we rotate the parent FrameNode ninety degrees into a horizontal stack (layout: 'stack', stackDirection: 'horizontal'), which we use for navigation bars, status pills, metric rows, and icon-plus-label lists. In a horizontal stack, the primary axis runs left-to-right, meaning every child set to width: '1fr' competes for a fractional slice of the horizontal row. If that horizontal parent frame itself is set to width: 'auto' (Fit Content)—such as a CTA button, a category pill, or a navbar link group—setting a child RichTextNode to width: '1fr' creates a circular layout dependency.

The parent frame asks the child text node how wide it needs to be, while the child text node asks the parent frame how much fractional space is left over. Framer's layout engine resolves this circular dependency by collapsing the RichTextNode's available width to the width of its widest single glyph, stacking the word vertically one letter per line ('P - R - I - C - I - N - G').

Therefore, Law #2 is absolute: inside any horizontal stack where children sit side-by-side in a pill, button, or navbar, every RichTextNode must be set to width: 'auto' and height: 'auto'. The only time a RichTextNode may use width: '1fr' inside a horizontal row is when the parent row has a definite width ('1fr' or fixed px) and the text sits beside a fixed-width icon or avatar that needs the text to wrap cleanly.

04
Elena Rostova
Perspective · Zurich / Berlin
"DESK 04 ERGONOMIC AUDIT: WHY EQUAL BOX HEIGHTS AND NON-WRAPPING NAVBARS ARE NON-NEGOTIABLE"

"Marcus's scene-graph laws are the programmatic enforcement of my Desk 04 UI specification. In institutional interface design, visual symmetry is a proxy for engineering reliability. When a horizontal navbar wraps a two-word link onto two lines because someone used a fixed width instead of width: 'auto', or when three pricing cards have jagged bottom borders because they lack height: '100%', my Hard Veto Gate triggers automatically. Precision at the node level is what makes our interfaces feel surgical."

4. Law #3: Achieving a 0px Sibling Height Delta in Multi-Column Grids

Walk through the Framer Marketplace with Elena Rostova from Desk 04 and Freya Lindholm from Desk 09, and you will see their #1 shared pet peeve within ten seconds: a 3-column or 4-column feature grid where Card 1 is 340 pixels tall, Card 2 is 388 pixels tall because its paragraph wrapped to an extra line, and Card 3 is 316 pixels tall. That jagged bottom edge immediately screams 'amateur template' to an enterprise design buyer.

In Framer's scene graph, uneven grid cards happen when builders leave the parent Grid FrameNode on an unaligned row height mode or set the child card frames to height: 'auto'. To guarantee a 0-pixel height delta across every card in a multi-column row, Desk 08 enforces a two-part scene-graph contract. First, on the parent Grid FrameNode, configure layout: 'grid', gridRowHeightType: 'fit' (Fit Content rows), and gridAlignment: 'stretch'.

Second, on every direct child FrameNode inside that multi-column grid, set width: '1fr' and height: '100%', with internal layout set to a vertical stack using stackDistribution: 'space-between' (or a top content stack paired with a pinned bottom footer). Now, whichever card has the longest copy dictates the track height of that row, and every sibling card stretches to match it to the exact sub-pixel.

5. Law #4: The Mobile 390px Grid Override ('height: 100%' -> 'height: auto')

Here is the subtle responsive trap that catches even experienced Framer engineers when they apply Law #3. When a 3-column desktop grid at 1440px cascades down to the 390px Phone breakpoint, we override the parent grid's column count to a single vertical column (gridColumnCount: 1). Because Framer breakpoints inherit properties from the primary Desktop canvas by default, those child cards still inherit height: '100%' inside the 1-column mobile grid.

If the parent mobile grid keeps equal-height track sizing across all stacked rows, or if a tall card forces every single-column row to match the tallest card in the set, smaller cards on mobile suddenly sprout eighty pixels of empty blank space at the bottom. Even worse, if a fixed row height leaks into mobile, long copy inside a card can clip or overflow its bottom border at 390px.

To prevent this, Desk 08's responsive scene-graph script explicitly overrides child card sizing on the 1-column Phone replica: while Desktop (1440px) and Tablet (810px multi-column) enforce width: '1fr', height: '100%', any 1-column mobile stack or 1-column grid replica overrides child card height to 'auto' so each stacked mobile card hugs its own content cleanly.

6. Case Study: Engineering Kyoto Atelier's Exposed 1px Swiss-Ma Grid Without a Single Broken Box

Nowhere are these four scene-graph laws tested more ruthlessly than in Kyoto Atelier, our architectural monograph system for design studios and brand flagships. Kenji Takahashi designed Kyoto Atelier with exposed 1-pixel structural hairlines (#D6D3CD) separating every grid cell on Warm Washi Paper (#F4F3EF). When your grid lines are literally drawn in high-contrast ink across the canvas, a 1-pixel height mismatch or an overflowing text node is visible from across the room.

Every multi-column bento showcase, typography specimen artboard, and W3C token table in Kyoto Atelier is constructed using gridRowHeightType: 'fit' on the parent frame and width: '1fr', height: '100%' on every cell. Inside each cell, our vertical stacks pair Cormorant Garamond editorial headings (width: '1fr', height: 'auto') with bottom-pinned Space Mono token badges (horizontal stacks with width: 'auto' children).

When Freya Lindholm ran Kyoto Atelier through her 3-breakpoint visual torture gate at 1440px, 810px, and 390px, all sixteen routes passed with a 0.0px sibling box height delta and zero mid-word character breaks. That is the difference between eyeballing boxes with a mouse and engineering a deterministic scene graph.

Key Takeaways

"Setting width: '1fr' on a RichTextNode inside an auto-width horizontal pill creates a circular layout dependency that collapses your copy into a 1-character-per-line vertical tower."

"Jagged card bottoms in a 3-column row are the instant tell of an amateur template—gridRowHeightType: 'fit' on the parent and height: '100%' on the children locks a 0px height delta."

"Mouse-driven guesswork builds fragile pages; deterministic scene-graph sizing laws build architectures that survive every founder edit from 1440px down to 390px."

The Convert Sprint Scene-Graph Sizing Matrix: Deterministic Node Rules by Parent Container Context

Parent Container ContextChild Node TypeMandatory Sizing SpecificationFailure Mode Prevented
Vertical Stack (Hero Column, Card Body, Section)RichTextNode (Headings, Paragraphs, Lists)width: "1fr" · height: "auto"Prevents unwrapped single-line text overflowing the right border
Horizontal Stack (Navbar, Badge Pill, Button)RichTextNode (Labels, Links, Badges)width: "auto" · height: "auto"Prevents 1-character-per-line vertical text collapse & wrapped nav links
Horizontal Stack (Icon + Wrapping Description Row)Icon Frame + Sibling RichTextNodeIcon: fixed px · Text: width: "1fr", height: "auto"Allows multi-line description wrapping beside a fixed-size icon
Multi-Col Grid (Desktop 1440px & Tablet 810px)Grid Parent + Direct Child Card FrameNodesParent: gridRowHeightType: "fit" · Child: width: "1fr", height: "100%"Eliminates uneven jagged bottom edges (>0px height delta) across rows
1-Col Mobile Grid Replica (Phone 390px)Direct Child Card FrameNodes in 1-Col StackOverride Child: width: "1fr" · height: "auto"Prevents excess empty bottom padding or clipped text on mobile screens
Scene-Graph Node Configuration: Equal-Height Multi-Column Grid + Safe RichText Sizing
// Deterministic Framer Scene-Graph Pattern enforced at Desk 08
const FeatureGridSceneGraph = {
  type: "FrameNode",
  name: "Bento Feature Grid",
  layout: "grid",
  gridColumnCount: 3,
  gridRowHeightType: "fit", // Stretches row track to tallest card
  gridAlignment: "stretch",
  gridGap: 24,
  children: [
    {
      type: "FrameNode",
      name: "Card 01",
      width: "1fr",
      height: "100%", // Matches tallest sibling in the row (0px delta)
      layout: "stack",
      stackDirection: "vertical",
      stackDistribution: "space-between",
      padding: 32,
      children: [
        {
          type: "FrameNode",
          name: "Badge Pill (Horizontal Stack)",
          layout: "stack",
          stackDirection: "horizontal",
          width: "auto",
          height: "auto",
          children: [
            { type: "RichTextNode", width: "auto", height: "auto", text: "01 // TOKEN SPEC" }
          ]
        },
        {
          type: "RichTextNode",
          name: "Card Title (In Vertical Stack)",
          width: "1fr",
          height: "auto",
          text: "W3C Design Token Parity"
        }
      ]
    }
  ]
};
Studio Review Case Study

During our Kyoto Atelier scene-graph audit, I discovered that the 3-column Monograph Archive grid had child cards set to height: 'auto' instead of height: '100%', resulting in a 28-pixel height mismatch between Card 1 and Card 2 at 1440px, while a horizontal filter pill used width: '1fr' on its text label. I triggered a Desk 08 veto, applied gridRowHeightType: 'fit' with child height: '100%' across all desktop/tablet multi-column grids, set mobile 1-column card overrides to height: 'auto', and locked all pill RichTextNodes to width: 'auto'.

Implementation Steps

STEP 01 · 0 Horizontal Text Overflows
Audit All Vertical Stack RichTextNodes

Inspect every heading and body text node inside vertical stacks and lock sizing to width: '1fr' (Fill) and height: 'auto' (Fit Content).

STEP 02 · 100% Single-Line Navbar & Pill Integrity
Lock Horizontal Pills & Navbars to width: 'auto'

Verify that every RichTextNode inside horizontal buttons, badges, and navbars uses width: 'auto' and height: 'auto' so text never wraps or stacks vertically.

STEP 03 · 0.0px Sibling Card Height Delta
Standardize Multi-Col Grids to height: '100%'

Set multi-column Grid parents to gridRowHeightType: 'fit' and direct child cards to width: '1fr', height: '100%' with space-between vertical distribution.

STEP 04 · Zero Dead Space or Clipping at 390px
Apply 390px 1-Column Mobile Height Overrides

On the 390px Phone breakpoint where grids collapse to 1 column, override child card height from '100%' to 'auto' so stacked cards fit their exact copy.

Frequently Asked Questions

Why did my text in Framer suddenly turn into a narrow 1-character-per-line vertical column?

This bug happens when a RichTextNode set to width: '1fr' (Fill) is placed inside a horizontal stack whose own width is set to 'auto' (Fit Content). Because the parent waits for the child to define its width while the child waits for the parent, Framer collapses the text width to a single letter. Change the RichTextNode width to 'auto' to fix it instantly.

How do I make all cards in a 3-column Framer grid stay the exact same height when one card has more text?

Select the parent Grid frame and set its row height mode to Fit Content (gridRowHeightType: 'fit') with stretch alignment. Then select every direct child card inside the grid and set its width to Fill ('1fr') and its height to Fill ('100%'), using a vertical stack with 'space-between' distribution inside each card.

Should a RichTextNode ever use height: '1fr' (Fill Height) in Framer?

No. Setting height: '1fr' on a RichTextNode decouples the text container from its typographic line-height box, which leads to clipped text on smaller screens or unpredictable spacing gaps. Always keep RichTextNode height set to 'auto' (Fit Content) and let parent FrameNodes handle spatial stretching.

Why do my equal-height grid cards have too much empty space at the bottom on mobile screens?

When a multi-column desktop grid collapses into a 1-column stack on the 390px Phone breakpoint, cards that inherit height: '100%' may stretch to match the tallest card in the entire set. On the Phone breakpoint, override the child cards' height property to 'auto' (Fit Content) so each vertically stacked card sizes naturally.

08
Marcus Chen · San Francisco / Taipei

Framer's layout engine is extraordinarily capable once you respect its mathematical invariants. Treat every container axis and fractional unit as a strict contract, and your layouts will hold their geometry under any content load.