Layout
svelterm implements the CSS layout models that make sense on a cell grid: block/inline flow, flexbox, grid, tables, and positioning. Lengths are cells; behaviour follows the specs linked below unless a grid deviation is noted.
Box model
Box model as standard: width/height (+ min-/max-), padding, margin (including margin: auto centring and vertical margin collapse), box-sizing: border-box | content-box. Borders are 1 cell thick when
present.
overflow: hidden | scroll | auto clips, and scrollable boxes really
scroll — mouse wheel, with fading scrollbar overlays. text-overflow: ellipsis needs the usual white-space: nowrap; overflow: hidden.
Scrolling is O(visible): subtrees outside the clip are culled from the
paint walk, so a 10,000-row list repaints in ~1.5 ms per scroll step
(initial layout still visits every row once). No windowing API needed —
put long content in an overflow: auto box and scroll it.
When the whole viewport scrolls (a fullscreen list, streaming inline output), the diff detects the vertical translation and emits a DECSTBM scroll-region command instead of rewriting every cell — an 80×40 screen scrolled one line is ~13× less output, which shows on slow links.
Display and flow
display: block, inline, inline-block, flex, grid, none, contents and
the full set of table display types. Consecutive inline-level children
form an inline formatting context, as in a browser: text flows across
inline element boundaries (a <strong>b</strong> c wraps as one
paragraph, with lines breaking mid-element where needed), whitespace
collapses per white-space: normal (runs of spaces and newlines become
one space, leading/trailing whitespace on each line is stripped), and text-align shifts each line box independently. Use white-space: pre to preserve spacing exactly — including rows built entirely of spaces,
such as game boards. Inline elements are style-only (no border, padding,
or margin); inline-block keeps the full box model and flows on the
line as an unbreakable unit.
Flexbox
Flexbox support: flex-direction (all four), flex-wrap, the flex shorthand
and flex-grow/flex-shrink/flex-basis, gap, justify-content (including the space-* distributions), align-items, align-self, order.
.toolbar { display: flex; gap: 1ch; justify-content: space-between; }
.spacer { flex: 1; } Grid
Grid support:
grid-template-columns/grid-template-rowswithcell/ch,%,fr,repeat(), andminmax().- Placement:
grid-columnandgrid-row(start,start / end,span n), numericgrid-area(r1 / c1 / r2 / c2). - Named areas:
grid-template-areaswithgrid-area: name;.is a hole; a repeated name spans its rectangle. Without a column template, areas split the width evenly.
.app {
display: grid;
grid-template-columns: 20ch 1fr;
grid-template-rows: 1ch 1fr 1ch;
grid-template-areas:
"header header"
"nav main"
"footer footer";
}
.nav { grid-area: nav; } grid-auto-flow: column fills down each column, wrapping to a new
(implicit) column after the explicit row count; implicit columns take
the last explicit column’s width. minmax() minimums on fr tracks
redistribute — a track clamped to its minimum leaves the pool and the
freed space re-splits among the remaining fr tracks.
Deviations: spanning content doesn’t stretch individual tracks.
Tables
Full CSS table layout: <table>/<thead>/<tbody>/<tfoot>/<caption>/<colgroup>, colspan/rowspan, table-layout: auto | fixed, border-spacing, caption-side, empty-cells, and border-collapse: collapse drawn with
shared box-drawing grid lines. Anonymous boxes are generated for stray
content. vertical-align: baseline is treated as top (one line of
cells has no baseline distinct from its top).
Positioning
position: absolute and fixed take elements out of flow and place them
by top/right/bottom/left with z-index stacking. position: relative shifts the element (and its descendants) visually while the
flow behaves as if it hadn’t moved, per spec. position: sticky pins an
element to the top of its scroll container once scrolled past
(top-edge only; it doesn’t yet push out at the end of its containing
block, and hit-testing targets the flow position rather than the stuck
one). A sticky element with a transparent background shows scrolled
content through it — give it a background. Sub-cell geometry
(transform, floats) is out of scope; see compatibility.
Sizing behaviours worth knowing
- Blocks fill their container’s width; inline-blocks shrink-wrap.
input/textarea/selecthave a minimum height of one row;<select>sizes to its longest option plus the▾indicator; checkboxes/radios are 3×1;progress/meterdefault to 20×1.@containersize queries evaluate against the nearest laid-out ancestor, in cells.