# 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
,overflow
notvisible
,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.
- 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 */
Copied!
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!
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!
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!
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!
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:0
for column direction) to allow shrinking. - Prefer
flex: 1 1 0
for equal columns that actually shrink;flex: 1
equals1 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!
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!
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
vsauto-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!
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!
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!
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!
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!
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!
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!
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!
Equal-Height Columns (Flex)
.cols { display: flex; gap: 1rem; } .cols > * { flex: 1 1 20rem; min-width: 0; }
Copied!
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!
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!
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: 0
is needed. - Implement a card grid that switches from
auto-fit
to a two‑columnminmax(0, 1fr)
layout at a container query breakpoint. - Add
aspect-ratio
to a media component and compareobject-fit: contain
vscover
. - Prototype a multi‑column article with a
column-span: all
pull 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-fit
andauto-fill
differ in Grid track repetition? - Why do flex items sometimes refuse to shrink, and how do you fix it?
- How does
aspect-ratio
interact with intrinsic sizing of replaced elements? - When should you use logical properties instead of physical ones?
- How do
scroll-snap-type
andscroll-padding
work together with sticky headers?
# Related Links
- /css/01-foundations.md
- /css/03-styling-techniques.md
- /css/05-variables-architecture.md