# 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
- Display & Formatting Contexts
- Intrinsic vs Extrinsic Sizing
- Aspect Ratio & Replaced Elements
- Positioning & Containing Blocks
- Floats, Shapes & Clear
- Flexbox: Deep Dive
- Alignment & Distribution
- Grid: Deep Dive
- Subgrid & Naming
- Multi-Column Layout
- Writing Modes & Logical Props
- Overflow, Scrolling & Snap
- Full‑Bleed & Centering Patterns
- Debugging & Tools
- Gotchas & Best Practices
- Quick Recipes
- Practice Tasks
- Review Questions
- Related Links
# 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,overflownotvisible,float,position: absolute|fixed,display: inline-block|table-cell|table, flex/grid items. - IFC (Inline Formatting Context): glyphs/inline boxes line-wrap;
line-heightcontrols line boxes. - FFC (Flex Formatting Context):
display: flex|inline-flexon container. - GFC (Grid Formatting Context):
display: grid|inline-gridon container.
- BFC (Block Formatting Context): isolates floats/margins; created by
- 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 */
2
3
4
5
6
7
8
Notes:
display: contentsaffects accessibility/semantics; ensure roles/labels remain on children as needed.flow-rootelegantly 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/heightor 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 */
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; }
2
Notes:
- Replaced elements (img, video, iframe) have intrinsic dimensions;
object-fit/object-positioncontrol content inside the content box. - If both width and height are auto but
aspect-ratiois 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;
}
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.stickyis 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; }
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:
- Determine flex base size (from
flex-basis, else content size orwidth/height). - Sum hypothetical sizes; compute free space.
- Distribute free space by
flex-grow(positive) orflex-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). Usemin-width:0(ormin-height:0for column direction) to allow shrinking. - Prefer
flex: 1 1 0for equal columns that actually shrink;flex: 1equals1 1 0%. - Use
gapinstead 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; }
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: baselinealigns text baselines; works with Grid line/baseline participation. - Safe alignment:
safe centeravoids overflow;unsafemay 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(…). frshares remaining free space after fixed tracks and gaps are resolved.
Auto‑placement:
grid-auto-flow: row|column|dense;denseback‑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; }
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-fitvsauto-fill:auto-fitcollapses empty tracks, enabling centering;auto-fillpreserves them as empty gutters.
Placement features:
- Line names:
[sidebar-start] 1fr [sidebar-end]and numeric lines. - Areas:
grid-template-areaswith named regions for readability. - Baselines:
align-items: baselinecan 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; }
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; }
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: avoidreduces 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);
}
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; }
2
3
4
5
6
7
8
9
Notes:
scrollbar-gutter: stableavoids layout shift when scrollbars appear.- Use
scroll-paddingto 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; }
2
3
4
5
6
7
Notes:
- Full‑bleed tracks make hero sections and carousels easy without hacking margins.
- Grid’s
place-items: centercenters 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-rootto see margin behavior; add background colors to identify tracks. - Use
content-visibility: auto+contain-intrinsic-sizein 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: 0on 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
orderand 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; }
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; }
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)); }
Equal-Height Columns (Flex)
.cols { display: flex; gap: 1rem; }
.cols > * { flex: 1 1 20rem; min-width: 0; }
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; }
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; }
2
# Practice Tasks
- Build a responsive article shell with a full‑bleed hero using named grid lines (
full,content). - Create a flex toolbar that handles overflow gracefully; prove why
min-width: 0is needed. - Implement a card grid that switches from
auto-fitto a two‑columnminmax(0, 1fr)layout at a container query breakpoint. - Add
aspect-ratioto a media component and compareobject-fit: containvscover. - Prototype a multi‑column article with a
column-span: allpull quote and discuss fragmentation trade‑offs.
# Review Questions
- What creates BFCs, and how do they affect floats and margin collapse?
- Explain min-content vs max-content sizing, and where each is useful.
- How do
auto-fitandauto-filldiffer in Grid track repetition? - Why do flex items sometimes refuse to shrink, and how do you fix it?
- How does
aspect-ratiointeract with intrinsic sizing of replaced elements? - When should you use logical properties instead of physical ones?
- How do
scroll-snap-typeandscroll-paddingwork together with sticky headers?
# Related Links
- /css/01-foundations.md
- /css/03-styling-techniques.md
- /css/05-variables-architecture.md