Bento
Relationships
Implemented by 1
Branches 2
Amendment (2026-06-08): absolute heading level, not relative depth
During implementation this decision's depth model was reversed: heading sugar now keys off the absolute heading level, not relative depth from an auto-detected base. The "relative heading depth (0 = shallowest, auto-detected base)" language throughout the sections below is superseded, as is the claim that "the absolute-vs-relative question dissolves" — it was resolved, in favour of absolute.
Shipped behaviour:
- Tiered sizing is a fixed level→size map:
#→full,##→large,###→medium,####+→small. Every heading becomes a cell (including#). levelsrungs are indexed by absolute heading level — rung 0 =#/h1, rung 1 =##/h2, rung 2 =###/h3, … — clamped to the last rung.levels="6,5,4,3,2,1"still revives span mode; the mapping is level→rung-index rather than depth-from-shallowest.
Why the reversal: absolute is local and predictable — a given heading level always yields the same tile, independent of its siblings. Auto-detection made a cell's size depend on what other headings happened to be in the grid (add a shallower heading and every other cell resizes), which is surprising to author and brittle under edits. The cost the original feared — "a grid that starts at h3 gets large cells" — is instead embraced as the honest, predictable rule (### is always medium), and full (h1) is now reachable from headings.
The rejected-alternatives analysis below still stands (faithful formula, proportional ladder, proportional entries); only the depth-indexing basis changed.
Context
A heading carries one signal: ordinal depth (h2 > h3 > h4 — prominence, one number). A bento cell needs a 2-D footprint (cols × rows) on the grid. So every heading-sugar "mode" is, underneath, just a projection function from depth → (cols, rows). There is nothing privileged about the tiered projection (SPEC-085's large=4×2, medium=3×1, small=2×1); it is one hardcoded choice. The old sizing="span" mode (spanForLevel = columns + 1 − level, rows=1) was simply a different hardcoded projection. They felt like "two completely different systems" only because each baked its projection into code.
SPEC-085 removed the span cell attribute and the sizing="span" parent mode as a "free cleanup — no content uses it." That reasoning does not hold up: absence of use is not absence of value, and a concrete need surfaced — a uniform-height, varied-width grid (the common "first cell wide, then a mix of halves/thirds" marketing/magazine layout), which tiered cannot express because its base rung (large) is 2 rows tall.
Several revivals were weighed and rejected (below). The throughline of the discussion: stop hardcoding the projection; make the depth→footprint mapping the attribute. A heading is well-suited to drive one dimension; which dimension(s), and by how much, should be the author's call — not a fixed preset.
Decision
Add a levels attribute to bento, governing the heading-sugar path only:
- Omitted → current tiered behavior, via the proportional
large/medium/smallpresets, which scale withcolumns. Unchanged and backward-compatible. - Provided → a comma-separated ladder, indexed by relative heading depth (0 = shallowest, auto-detected base). Each rung:
W(bare integer) →cols=W, rows=1WxH→cols=W, rows=H
- Rungs are absolute against the declared
columns; the author keepscolumnsandlevelsin sync. No proportional entries inlevelsfor now. - Ladders shorter than the deepest heading clamp to the last rung.
- Explicit
{% bento-cell %}grids ignorelevels— the two front doors (heading sugar vs explicit cells) are unchanged. - The removed span mode is exactly reproducible as
levels="6,5,4,3,2,1".
The proportional default and the absolute override coexist without conflict: "no proportional entries" constrains only what an author may write into levels, not the built-in default's internal (proportional) representation.
No sizing attribute is revived, and no span mode returns. levels subsumes both; the SPEC-085 cruft stays dead.
Rationale
The maintenance and conceptual cost of "modes" was the hardcoded projection, not the heading sugar itself. Making the projection an author-supplied ladder collapses tiered, span, and feed layouts into one system that differs only by the ladder's contents — exactly the unification the discussion was reaching for. Numeric-only rungs keep the MVP small and unambiguous to parse (x → WxH; integer → width-only), while the proportional default preserves the columns-safe zero-config experience nobody should have to opt out of.
The bare-integer form directly honors the observation that headings are suited to control one dimension — levels="6,5,4,3,2,1" is pure width-by-depth — while WxH keeps the 2-D door open for those who want it.
Consequences
Amendment to SPEC-085. The sugar path becomes configurably expressive — including rows-by-depth — superseding SPEC-085's "deliberately blunt, three coarse tiers, rows-by-depth rejected (it inverts hierarchy)" stance. What makes that cheap: explicit cells already permit any footprint, including hierarchy-inverting ones; SPEC-085 only constrained the sugar path and pushed that power into explicit cells. levels adds no new grid capability — it only makes the existing expressiveness reachable from headings with less syntax. The "inverts hierarchy" footgun was always reachable via explicit cells; levels hands it to the author knowingly, in exchange for the ergonomics.
For @refrakt-md/marketing: add the levels attribute to the bento schema; in the heading→cell conversion, when levels is present, parse the ladder and assign each converted cell its cols/rows by the heading's relative depth (clamping to the last rung), short-circuiting tieredSize. Default path unchanged.
For @refrakt-md/lumina: no new CSS — cells already render cols/rows spans. Composes with the existing row-height and content-height attributes.
For docs: document levels on the bento authoring page, with the levels="6,5,4,3,2,1" recipe called out as the "uniform-width grid" / former span-mode equivalent.
Tracked by: WORK-356 (queued; design is settled, implementation intentionally left to marinate).
Open follow-up:
- Proportional rungs in
levels(option 4) if a columns-safe explicit ladder is ever wanted — grammar is forward-compatible. - Named ladder presets (e.g.
levels="strips") as sugar over common ladders, if the explicit list proves too verbose in practice.