Repository navigation
Layout
Layout is a pure function of the styled tree and the viewport: styles in, an immutable fragment tree out, in page coordinates. Painting consumes fragments only.
- Block containers stack their block children; inline content is broken into line boxes with greedy breaking, whitespace collapsing per
white-space(normal,nowrap,pre,pre-wrap,pre-line), an emergency break inside a word that cannot fit a line, andtext-align. - Margins collapse per CSS 2.1 §8.3.1: between siblings, through a parent's open top and bottom edges, and through empty boxes; a cleared box keeps its margin inside, and an empty box holding a float ends the walk.
- Percentage widths resolve against the containing block; percentage heights (and
min-height,max-height) against a definite containing height — a written length, a percentage of a definite height in turn, a flex line's settled size, an absolutely positioned box's containing block, or the viewport for the root — and stayautowithout one. -
min-width,max-width,min-heightandmax-heighthold blocks, floats, flex items and replaced boxes. -
box-sizing:content-box(the initial value) andborder-box, under which a writtenwidth,height,min-/max-size or flex basis names the border box — the padding and the borders come off it, and the content floors at zero when they are wider than the size written. A form control is sized whole either way: its own border and padding live inside the size it reports. - Lists get their markers (disc, circle, square, decimal, none).
- An inline box draws its own background and border and takes room for its margin, padding and border where it opens and where it closes. Broken over several lines it is one box sliced: the line it carries on to draws neither the edge it never reached nor the one it has not come to. Broken around a block it is two complete boxes, each with all four of its edges.
- A block-level box inside an inline box splits the inline box around it and lays out as a block child of the containing block (CSS 2.1 §9.2.1.1): a card inside a link keeps its border, padding and background.
- The line box follows CSS 2.1 §10.8: every box on the line reaches above and below the baseline it is aligned to — the strut of the block's font, text by its ascent and descent within its line height, a picture by its height, an inline-block by its own ascent and descent — and the line runs from the uppermost top to the lowermost bottom.
-
vertical-alignon inline boxes and atomic boxes alike:baseline,sub,super,text-top,text-bottom,middle,top,bottom, a length, or a percentage of the box's own line height. A run inside nested spans takes the alignment of the nearest raised or lowered inline box around it;topandbottomboxes sit at the line's edges and grow the line when taller. -
line-height: normalis what the face asks for (its ascent, descent and line gap); a written line height places the baseline by the half-leading model.
display: inline-block, inline-flex and inline-grid (and inline-table until tables land) lay out as one atomic box on the line: shrink-to-fit wide like a float, the margin box what the line holds, sitting on the baseline of its last line box — its bottom margin edge when it has none, and the higher of the two when it clips its overflow, as CSS 2.2 has it. An absolutely positioned inline-block becomes a block with an inline static position.
-
float: leftandfloat: right, placed at their point in flow — mid-line too — no higher than an earlier float, below what their ownclearnames, then down until they fit beside the floats at that height. -
clearon blocks and on<br>(the CSS property or theclearattribute). - Auto widths shrink to fit from the min-content and max-content widths of the float's contents.
- Boxes with their own formatting context (
overflowother thanvisible,display: flow-root, flex containers, inline-blocks, floats themselves) contain their floats and sit beside outside floats — narrowed, or below them when a written width does not fit. - Line boxes and formatting-context boxes keep clear of floats along their whole height (CSS 2.1 §9.5), not only at their top: a float starting lower narrows the line, or moves it below the next float when its content no longer fits.
display: flex and inline-flex: the items (element children in order, the container's own text as anonymous items, order sorted), each item's flex base size and automatic minimum, lines (flex-wrap, both directions), flexible lengths (grow into free space or shrink out of overflow, weighted, never below the minimum, with items frozen at their minimum and the rest re-shared), cross sizes, align-items/align-self (stretch, flex-start, flex-end, center; baseline as flex-start for now), align-content across wrapped lines, justify-content (all six values, the reverse directions swapping the ends), row-gap/column-gap/gap, flex-direction in all four directions, and the flex and flex-flow shorthands. A single-line container gives its line the container's cross size; a wrapping container whose items fit one line keeps that line its items' size.
Auto margins on items are zero for now (no margin centering, and no stretch prevention), and baseline alignment is not written.
display: grid and inline-grid, css-grid-1 without subgrid and masonry:
-
The explicit grid —
grid-template-columnsandgrid-template-rowstrack lists: lengths and percentages,fr,auto,min-content,max-content,minmax(),fit-content(),repeat()with a count orauto-fill/auto-fit(as many repetitions as fit;auto-fitcollapses the empty ones), and line names in brackets;grid-template-areas(each area a rectangle, or the declaration is dropped) with the-start/-endline names it implies; thegrid-templateandgridshorthands,grid-auto-flowincluded. -
Placement —
grid-row,grid-column,grid-areaand their longhands: line numbers (negative from the end), the nth line with a name, a name alone (its area's edge, else the first so named),spanby count or to a named line; lines outside the explicit grid make implicit tracks, sized bygrid-auto-rows/grid-auto-columns(the pattern runs forward after the grid and backward before it). Auto-placement (css-grid-1 §8.5) in row or column flow, sparse ordense, inorder-modified document order; the container's own text becomes anonymous items, its::before/::afterboxes items placed by their own properties. -
Track sizing — the algorithm of css-grid-1 §11: base sizes and growth limits from the items' minimum, min-content and max-content contributions (single-track items first, then spanning items by span, then items crossing flexible tracks), the free space maximizing the tracks,
frshares found by the fr-size search, andautotracks stretched byjustify-content/align-content: normalorstretch. Percentage tracks and gaps resolve against the container's content box; under an indefinite height they count as auto while the content height is found, then resolve against it and the rows are sized again. -
Alignment —
justify-contentandalign-contentdistribute the free space between the tracks (start,end,center,space-between,space-around,space-evenly,stretch);justify-items/justify-selfandalign-items/align-selfplace an item in its area (stretch,start,end,center;normalstretches a block and keeps a picture or control at its own size;baselineisstartfor now); auto margins take the free space first;place-items,place-selfandplace-content. A grid item's percentages resolve against its area.z-indexon a grid (or flex) item orders it among its container's positioned boxes. -
Sizing the container — an inline-grid, a float or a flex item that holds a grid shrinks to fit: the columns sized under a min-content and a max-content constraint, gaps included.
-
Absolute positioning (css-grid-2 §9) — an absolutely positioned child of a grid container is not a grid item, but when the container is also its containing block its placement still names a grid area, and that area is the containing block: an offset counts from the area's edge, a box with auto offsets stands at the area's corner and shrinks to fit, and a box stretched between opposite offsets fills the area. A property naming a line the grid does not have counts as
auto, and anautoedge stays on the container's padding edge, so one axis can be the area's and the other the padding box's.
Baseline alignment, subgrid and grid-lanes are not written.
-
position: relativeshifts a box after layout without touching the flow.stickystays put until scroll containers land. -
position: absoluteandfixed: the box is placed in the nearest positioned ancestor's padding box (or the viewport) by its offsets — width as written, stretched betweenleftandright, else shrink-to-fit in what the offsets leave; height likewise; over-constrained boxes solve their auto margins; a box with no offsets stands at its static position, where it would have been in flow. Replaced boxes keep their own size; the offsets place them without stretching. - Painting follows CSS 2.1 Appendix E: a positioned box with a
z-indexis a stacking context painted as one unit at its level; negative levels go under the context's own flow.
visibility: hidden keeps a box's room and paints nothing (a visible descendant paints). opacity: 0 hides a box and everything in it; between zero and one the box paints as if opaque for now. overflow other than visible clips what a box contains to its padding box, positioned descendants included when the box is their containing block.
The translations of transform (translate, translateX, translateY, translate3d, added up along a list) and of the translate property move a box after layout, percentages of its own size; any transform makes the box a stacking context. Rotations, scales and skews are passed over, leaving the box where it is.
- Pictures are sized by CSS, by their
width/heightattributes, or by themselves, the ratio kept; a picture wider than its container shrinks to fit.srcset,sizesand<picture>choose the source for the viewport (see Painting and text). - An
iframe,canvas,video,embedorobjectis a box of its own too — 300 by 150 when nothing sizes it, as CSS 2.1 §10.3.2 has it — and none of them show their children. - On a line, a replaced box carries its margins, border and padding; the picture sits inside them and the bottom margin edge rests on the baseline.
Text fields, password fields, textareas, checkboxes, radio buttons, selects and buttons lay out as atomic boxes on the baseline, sized by their kind (size, cols/rows, the caption, the widest option) or by CSS, with their margins around them; block-level controls stand on their own. See The shell for how they behave.
CSS 2.1 §17, the separated border model:
-
Structure — every
displayvalue of the table model:table,inline-table, the row groups (theadfirst andtfootlast, wherever they stand), rows, cells withcolspanandrowspan(arowspanof 0 reaches the end of its group), columns and column groups withspan, captions (caption-side: toporbottom). The anonymous boxes of §17.2.1 are generated: a run of table parts outside a table gets an anonymous table around it (an inline-table inside inline content), loose content in a table or a row group gets an anonymous row, and loose content in a row an anonymous cell, blank text between parts dropped. -
Widths — the automatic layout of §17.5.2.2: each column's minimum and maximum from its cells' content and written widths, spanning cells widening the columns they span in proportion, percentage columns taking their share first, written widths holding, the other columns sharing the rest — their maximums when it fits, a point between their minimums and maximums when not. A table's width is what it is written to be (an HTML
table's border box; another element's content box), else it shrinks to fit the room;table-layout: fixedtakes the widths of the columns and of the first row's cells and shares the rest equally.border-spacingand the table's border and padding count in. -
Heights — a row is as tall as its tallest cell, the baseline-aligned ones lined up first; a spanning cell that needs more gets it from the last row it spans; a written row or cell height is a floor; a written table height stretches the rows in proportion. Cells sit in their rows by
vertical-align(top,middle— the row groups' default —bottom,baseline). - Painting — the table's border and background, the column groups' and columns' backgrounds under the rows, the row groups' and rows' under the cells, and each cell's own border and background; the table's baseline is its first row's.
-
Presentational attributes — the HTML rendering section's mappings arrive as author declarations of zero specificity:
width,height,bgcolor,align,valign,nowrapon the table parts (andalign/bgcolor/textonbody,div,p, headings,hr,imgwithhspace/vspace/border,fontwithcolor/size/face), and a table'scellspacing,cellpaddingandborder, the last two reaching its cells.
The collapsing border model (border-collapse: collapse, CSS 2.1 §17.6.2) lays out with no gutters and no table padding, and the borders merge. At every segment of every grid line the table, its column groups, columns, row groups, rows and cells all offer a border, and §17.6.2.1 picks one: a hidden border takes the line away outright, none loses to everything, otherwise the widest wins and equal widths go to the box that comes first in the list cell, row, row group, column, column group, table. The winner runs down the middle of the line and the boxes on either side each keep half of it, so the shared line is drawn once at its full width; a box that spans takes the widest segment along each of its edges, and the table box keeps the outer half of its outermost lines. empty-cells: hide and visibility: collapse on rows and columns are not written.
sashfold --render page.html -o out.png --dump-layout
prints every fragment — tag, id and class, position, size, baseline, and flags for floats, positioned boxes and stacking contexts — and every text run with its position, baseline and width.
Getting started
What works today
Measured
Design decisions
Testing and tools