Phase 9: Advanced Layout#
Implement vertical margin collapsing for adjacent block-level elements per the CSS specification.
Current State#
- Block layout stacks children vertically using
margin_box_height()which simply sums margin + border + padding + content height - Adjacent vertical margins are NOT collapsed — they stack, producing double spacing
- This causes incorrect spacing compared to browser behavior (e.g., two
<p>elements withmargin: 1emshould have 1em gap, not 2em)
Requirements#
- Adjacent sibling collapsing: When two block-level siblings are adjacent (no border/padding between them), collapse their adjoining margins — the gap is
max(bottom_margin, top_margin), not the sum - Parent-child collapsing: A parent's top margin collapses with its first child's top margin if there is no border, padding, or inline content separating them. Same for bottom margin with last child
- Empty block collapsing: An empty block's top and bottom margins collapse with each other
- Negative margins: When one margin is negative, the collapsed margin is
max_positive + min_negative. When both are negative, use the more negative value - Collapsing is blocked by:
- Elements with
overflowother thanvisible - Floated elements
- Absolutely positioned elements
- Inline-block elements
- Elements with border or padding between margins
- Elements with
Files to Modify#
crates/layout/src/lib.rs— Rewritelayout_block_children()to track and collapse margins instead of naively stacking
Tests#
- Two adjacent
<p>elements: gap equals the larger margin, not the sum - Parent with no padding/border: first child's top margin collapses with parent's
- Negative margin collapsing: correct result for positive+negative and negative+negative cases
- Collapsing blocked by border/padding between elements
- Empty block margin collapsing
Acceptance Criteria#
- Adjacent sibling vertical margins collapse correctly
- Parent-first-child and parent-last-child collapsing works
- Negative margins handled per spec
- All tests pass, clippy clean, fmt clean