# Layout Essentials

Mastering layout means understanding how boxes are generated, sized, aligned, and positioned. This guide goes beyond basics, explaining the visual formatting model, formatting contexts, intrinsic sizing, and modern layout systems (Flexbox, Grid, Multicol) with practical patterns and pitfalls.

# Table of Contents

# Visual Formatting Model

  • Normal flow: block boxes stack vertically; inline boxes form lines. Outside normal flow: floats and positioned elements.
  • Formatting contexts:
    • BFC (Block Formatting Context): isolates floats/margins; created by flow-root, overflow not visible, float, position: absolute|fixed, display: inline-block|table-cell|table, flex/grid items.
    • IFC (Inline Formatting Context): glyphs/inline boxes line-wrap; line-height controls line boxes.
    • FFC (Flex Formatting Context): display: flex|inline-flex on container.
    • GFC (Grid Formatting Context): display: grid|inline-grid on container.
  • Containing block: reference rectangle for percentage and positioned layout; depends on position, writing mode, and transforms.

# Display & Formatting Contexts

The two‑value display syntax separates outer/inner display types.

/* Equivalent shorthands */
.block { display: block; }                 /* block flow */
.flowroot { display: flow-root; }          /* block flow-root (BFC) */
.flex { display: flex; }                   /* block flex */
.inlineflex { display: inline flex; }      /* inline flex */
.grid { display: grid; }                   /* block grid */
.contents { display: contents; }           /* no box; children participate */
.list { display: list-item; }              /* adds marker box */
Copied!
1
2
3
4
5
6
7
8

Notes:

  • display: contents affects accessibility/semantics; ensure roles/labels remain on children as needed.
  • flow-root elegantly replaces clearfix hacks for containing floats and preventing margin collapse.

# Intrinsic vs Extrinsic Sizing

  • Intrinsic sizes: min-content (tightest without overflow), max-content (longest unbroken), fit-content.
  • Extrinsic sizes: controlled by width/height or constraints from the containing block.
  • Definite vs indefinite sizes: percentages resolve only against definite sizes (e.g., a child height: 50% needs a definite parent height).
.tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(min-content, 1fr));
}
.title { width: min(60ch, 100%); } /* cap by characters or container */
Copied!
1
2
3
4
5

Key rules:

  • min-content, max-content, fit-content(…) are especially useful in Grid track sizing.
  • Flex items have an automatic minimum size (min-content) unless min-width/height: 0; this often causes overflow surprises.

# Aspect Ratio & Replaced Elements

aspect-ratio participates in intrinsic sizing and works with or without explicit width/height.

.media { aspect-ratio: 16 / 9; }
.card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
Copied!
1
2

Notes:

  • Replaced elements (img, video, iframe) have intrinsic dimensions; object-fit/object-position control content inside the content box.
  • If both width and height are auto but aspect-ratio is set, the used size is inferred from available space.

# Positioning & Containing Blocks

Position schemes: static (default), relative, absolute, fixed, sticky.

.tooltip { position: relative; }
.tooltip > .tip {
  position: absolute; inset-block-end: 100%; inset-inline-start: 50%;
  transform: translateX(-50%);
  padding: .25rem .5rem; background: #111; color: #fff; border-radius: .25rem;
}
Copied!
1
2
3
4
5
6

Containing blocks:

  • Absolutely positioned elements use the nearest ancestor with a non‑static position as containing block; else the initial containing block.
  • transform, filter, perspective, and certain containments can establish containing blocks for positioned descendants.
  • sticky is relative to its nearest scroll container and respects its padding edge.

Tip: For predictable sticky, ensure the ancestor scroll container has a definite height and overflow not visible.

# Floats, Shapes & Clear

Floats remove the element from normal flow and allow inline content to wrap around. Use sparingly for text wrap effects; prefer modern layout for structure.

.avatar { float: inline-start; shape-outside: circle(50%); shape-margin: .5rem; margin: 0 1rem .5rem 0; }
article::after { content: ""; display: block; clear: both; }
Copied!
1
2

Notes:

  • Create a BFC (e.g., flow-root) to contain floats and stop margin collapse.
  • Shape functions: circle(), ellipse(), inset(), or an alpha channel from an image URL.

# Flexbox: Deep Dive

Flexbox is one‑dimensional (main vs cross axis).

Container:

  • display: flex|inline-flex, flex-direction, flex-wrap, gap
  • Alignment: justify-content (main), align-items (cross), align-content (multi‑line)

Item:

  • flex: <grow> <shrink> <basis>; align-self; order (visual only; do not rely for tab/reading order)

Algorithm essentials:

  1. Determine flex base size (from flex-basis, else content size or width/height).
  2. Sum hypothetical sizes; compute free space.
  3. Distribute free space by flex-grow (positive) or flex-shrink (negative), subject to min/max constraints.

Common pitfalls and fixes:

  • Automatic minimum size: Flex items default to min-width:auto (their min-content size). Use min-width:0 (or min-height:0 for column direction) to allow shrinking.
  • Prefer flex: 1 1 0 for equal columns that actually shrink; flex: 1 equals 1 1 0%.
  • Use gap instead of margins for predictable spacing.
.toolbar { display: flex; align-items: center; gap: .5rem; }
.spacer { flex: 1 1 auto; } /* pushes siblings apart */

.cards { display: flex; gap: 1rem; }
.cards > article { flex: 1 1 16rem; min-width: 0; }
Copied!
1
2
3
4
5

# Alignment & Distribution

Applies to Flex and Grid (with subtle differences).

  • Main axis: justify-content: start|center|end|space-between|space-around|space-evenly|stretch
  • Cross axis: align-items, align-content (multi‑line), align-self
  • Shorthands: place-content, place-items, place-self
  • Baseline alignment: align-items: baseline aligns text baselines; works with Grid line/baseline participation.
  • Safe alignment: safe center avoids overflow; unsafe may overflow.

# Grid: Deep Dive

Grid is two‑dimensional with explicit and implicit tracks.

Track sizing:

  • Fixed: 200px, fluid: 1fr, min/max: minmax(10rem, 1fr), content‑based: min-content, max-content, fit-content(…).
  • fr shares remaining free space after fixed tracks and gaps are resolved.

Auto‑placement:

  • grid-auto-flow: row|column|dense; dense back‑fills holes but may reorder visually.
  • Implicit tracks size via grid-auto-rows|columns.

Responsive patterns:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
}

/* Prevent overflow in nested grids */
.grid-min0 { display: grid; grid-template-columns: 1fr minmax(0, 2fr); gap: 1rem; }
Copied!
1
2
3
4
5
6
7
8

Pitfalls:

  • Use minmax(0, 1fr) in tracks that hold long content to allow it to shrink without overflow.
  • auto-fit vs auto-fill: auto-fit collapses empty tracks, enabling centering; auto-fill preserves them as empty gutters.

Placement features:

  • Line names: [sidebar-start] 1fr [sidebar-end] and numeric lines.
  • Areas: grid-template-areas with named regions for readability.
  • Baselines: align-items: baseline can align across rows/columns when supported.

# Subgrid & Naming

subgrid lets a child grid inherit track sizing from its parent for rows, columns, or both.

.layout { display: grid; grid-template-columns: [full-start] 1fr [content-start] min(70ch, 100%) [content-end] 1fr [full-end]; }
.article { display: grid; grid-template-columns: subgrid; grid-column: content; gap: 1rem; }
Copied!
1
2

Notes:

  • Subgrid simplifies consistent gutters/lines across nested components.
  • Name your lines and areas thoughtfully; it pays off in large layouts.

# Multi-Column Layout

Columns fragment content like newspapers.

.news { column-width: 22rem; column-gap: 2rem; }
.callout { column-span: all; }
.card { break-inside: avoid; }
Copied!
1
2
3

Key props: column-count, column-width, column-gap, column-rule, column-fill: balance|auto, column-span: all.

Notes:

  • Fragmentation can break complex components; avoid placing large widgets inside columns.
  • break-inside: avoid reduces fragmenting of blocks (respect varies by browser).

# Writing Modes & Logical Props

Internationalization requires layout that adapts to writing direction.

/* Vertical text example */
.vcard { writing-mode: vertical-rl; text-orientation: mixed; }

/* Logical properties respect direction and writing-mode */
.box {
  margin-block: 1rem; padding-inline: 1rem;
  border-block-start: 2px solid var(--accent);
}
Copied!
1
2
3
4
5
6
7
8

Use writing-mode, direction, logical sizes (inline-size, block-size), and logical margins/padding/borders for adaptable layouts.

# Overflow, Scrolling & Snap

Control scroll containers and behavior.

.pane { overflow: auto; scrollbar-gutter: stable both-edges; }

/* Scroll snap carousel */
.carousel { display: grid; grid-auto-flow: column; gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding: 1rem; }
.carousel > * { scroll-snap-align: start; }

/* User experience and containment */
html { scroll-behavior: smooth; }
.no-bounce { overscroll-behavior: contain; }
Copied!
1
2
3
4
5
6
7
8
9

Notes:

  • scrollbar-gutter: stable avoids layout shift when scrollbars appear.
  • Use scroll-padding to ensure snap positions account for sticky headers.

# Full‑Bleed & Centering Patterns

/* Centered column with full‑bleed escapes */
.page { display: grid; grid-template-columns: [full-start] 1fr [content-start] min(70ch, 100%) [content-end] 1fr [full-end]; }
.content { grid-column: content; }
.fullbleed { grid-column: full; }

/* Perfect centering */
.center { min-block-size: 100svh; display: grid; place-items: center; }
Copied!
1
2
3
4
5
6
7

Notes:

  • Full‑bleed tracks make hero sections and carousels easy without hacking margins.
  • Grid’s place-items: center centers both axes succinctly.

# Debugging & Tools

  • Use DevTools overlays for Grid/Flex; toggle line numbers, track sizes, and gaps.
  • Add a debug helper: .debug * { outline: 1px dashed rgba(0,0,0,.2); }.
  • Reveal formatting contexts: temporarily add display: flow-root to see margin behavior; add background colors to identify tracks.
  • Use content-visibility: auto + contain-intrinsic-size in long lists for performance (see Foundations).

# Gotchas & Best Practices

  • Prefer layout systems (Grid/Flex) over floats for structure; reserve floats for text wrap.
  • Avoid fixed heights; use min-height/max-height, aspect-ratio, or intrinsic sizing.
  • For Flexbox overflow, remember min-width: 0 / min-height: 0 on items.
  • In Grid, use minmax(0, 1fr) to prevent overflow from long content.
  • Stick to logical properties for internationalization.
  • Use container queries when component layout must adapt to parent size.
  • Keep order and visual reordering to a minimum (accessibility/reading order).

# Quick Recipes

Sticky Footer (Flex)

.page { min-block-size: 100svh; display: flex; flex-direction: column; }
.main { flex: 1 1 auto; }
.footer { margin-block-start: auto; }
Copied!
1
2
3

Holy Grail (Grid)

.holy {
  display: grid;
  grid-template-columns: 16rem 1fr 16rem;
  grid-template-rows: auto 1fr auto;
  min-block-size: 100svh; gap: 1rem;
}
.header, .footer { grid-column: 1 / -1; }
.nav { grid-column: 1; }
.content { grid-column: 2; }
.aside { grid-column: 3; }
Copied!
1
2
3
4
5
6
7
8
9
10

Responsive Cards (Grid auto-fit)

.cards { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
Copied!
1

Equal-Height Columns (Flex)

.cols { display: flex; gap: 1rem; }
.cols > * { flex: 1 1 20rem; min-width: 0; }
Copied!
1
2

Sticky Sidebar

.layout { display: grid; grid-template-columns: 20rem 1fr; gap: 1rem; }
.sidebar { position: sticky; top: 1rem; align-self: start; max-block-size: calc(100svh - 2rem); overflow: auto; }
Copied!
1
2

Carousel with Scroll Snap

.carousel { display: grid; grid-auto-flow: column; gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory; }
.carousel > * { scroll-snap-align: start; }
Copied!
1
2

# Practice Tasks

  1. Build a responsive article shell with a full‑bleed hero using named grid lines (full, content).
  2. Create a flex toolbar that handles overflow gracefully; prove why min-width: 0 is needed.
  3. Implement a card grid that switches from auto-fit to a two‑column minmax(0, 1fr) layout at a container query breakpoint.
  4. Add aspect-ratio to a media component and compare object-fit: contain vs cover.
  5. Prototype a multi‑column article with a column-span: all pull quote and discuss fragmentation trade‑offs.

# Review Questions

  1. What creates BFCs, and how do they affect floats and margin collapse?
  2. Explain min-content vs max-content sizing, and where each is useful.
  3. How do auto-fit and auto-fill differ in Grid track repetition?
  4. Why do flex items sometimes refuse to shrink, and how do you fix it?
  5. How does aspect-ratio interact with intrinsic sizing of replaced elements?
  6. When should you use logical properties instead of physical ones?
  7. How do scroll-snap-type and scroll-padding work together with sticky headers?
  • /css/01-foundations.md
  • /css/03-styling-techniques.md
  • /css/05-variables-architecture.md