Skip to content

How much fits

Every layout has a point where it stops working. A card grid reads at three; at eight it is a wall. Nothing in the CSS prevents the eighth card: it renders, it is just bad.

So each component declares its own limits, and the tooling holds authors to them.

"capacity": {
"axis": "item",
"sweet": 3,
"soft": 4,
"hard": 5,
"escalateTo": ["list-tabular"],
"note": "past five reasons it reads as a list, not a position"
}
  • axis — what you are counting, from a fixed set of five: item, row, col, cell, line. Anything else fails validation, so a layout counting reasons or cards says item, a table says row, and a grid of columns says col. Put the human word in note.
  • sweet — where the layout is at its best.
  • soft — still fine.
  • hard — the ceiling. Past this the linter tells the author to move.
  • escalateTowhich component to move to. This is the field that makes the limit useful rather than annoying: it turns “too many” into “use list-tabular instead.”

Declaring a capacity means also shipping a stressDoc — a sample at the hard limit, so the ceiling is a thing someone rendered and looked at rather than a number someone guessed.

"density": { "axis": "item", "soft": 15, "hard": 24,
"note": "aim for about fifteen words per reason" }

Capacity counts the items; density is how much fits inside one. Four cards of six words each and four cards of forty are different slides, and only one of them is readable from the back of a room.

Do not guess these numbers. Add items until the slide stops working, and write down where that was.

Find the ceiling yourself

Try this. On the Slide tab, keep adding reasons. The count where it first feels crowded is your soft limit; one before unusable is your hard limit. Now double the length of every reason and run it again — the same slide fails several items earlier.

Three things, escalating:

  1. The deck linter warns, naming the component you escalate to.
  2. The engine measures the rendered slide and flags a real overflow — content that does not fit the page rather than content that merely reads badly.
  3. Nothing blocks the render.

That last one is the posture throughout Lattice: warn, explain, suggest the fix. An author with a reason to break a rule keeps their slide.

A component can also declare that it rearranges for narrow or square page shapes:

"adapt": { "mode": "reflow" }

Then scope the reflow rules by the slide’s family:

section.takeaway.takeaway:where([data-family="square"], [data-family="tall"], [data-family="strip"])
> .cell-stage > ul { /* one column instead of two */ }

The engine stamps data-family on the section from the deck’s page shape. Wide is the default and carries no stamp, so name the shapes you are targeting and leave wide out.

Ship your component — the files, the gates, and what to check before you push.