Layout Fundamentals
Layout is how elements are positioned and sized in a document. CSS offers several layout systems, each suited to different tasks: normal flow (default, block-and-inline layout), positioning (absolute, fixed, relative), flexbox (one-dimensional), and grid (two-dimensional). Understanding layout starts with the display property, which determines how an element participates in the layout.
Layout systems and their purposes
System | Dimensions | Best for | Learning curve |
|---|---|---|---|
Normal flow | One-dimensional (block/inline) | Documents, basic layouts | Easy |
Positioning | Manual positioning | Overlays, modals, precise control | Medium |
Floats | One-dimensional | Images with text wrapping (legacy) | Medium |
Flexbox | One-dimensional (rows or columns) | Navigation, buttons, component layouts | Medium |
Grid | Two-dimensional (rows and columns) | Page layouts, dashboards, complex grids | Hard |
How layout works
Every HTML element generates a box in the layout. The browser positions that box based on:
- Element type — whether the element is inline, block, or something else
- Display property — how the element generates boxes (display: block, inline, flex, grid, etc.)
- Containing block — the parent element or viewport that constrains positioning
- Position property — whether the element is positioned relative to normal flow (static, relative, absolute, fixed)
- Sibling elements — how space is shared with other elements
- Constraints — width, height, margin, padding, and other sizing properties
/* The foundation: the display property */
.element {
display: block; /* full width, stacks vertically */
display: inline; /* only takes needed width, flows with text */
display: inline-block; /* inline but respects width/height */
display: flex; /* flexible layout, one direction */
display: grid; /* powerful two-dimensional layout */
display: none; /* not rendered, not in layout */
}
/* Positioning context */
.positioned {
position: static; /* default, follows normal flow */
position: relative; /* positioned relative to its normal position */
position: absolute; /* positioned relative to nearest positioned ancestor */
position: fixed; /* positioned relative to viewport */
position: sticky; /* switches between relative and fixed */
}Block vs inline
Property | Block | Inline |
|---|---|---|
Width | Fills 100% of parent | Only takes needed space |
Height | Respects height property | Height property ignored |
Margin | All sides work | Top/bottom ignored |
Padding | All sides work | Top/bottom expand outside box |
Stacking | Stacks vertically | Flows horizontally with text |
Examples |
|
|
/* Block elements stack vertically */
<div>Block 1</div>
<div>Block 2</div>
/* Results in */
Block 1
Block 2
/* Inline elements flow horizontally */
<span>Inline 1</span>
<span>Inline 2</span>
/* Results in */
Inline 1 Inline 2
/* CSS control */
.block-element {
display: block;
width: 200px; /* width works */
height: 100px; /* height works */
margin: 10px; /* all margins work */
}
.inline-element {
display: inline;
width: 200px; /* ignored */
height: 100px; /* ignored */
margin: 10px 0; /* top/bottom ignored */
}The containing block
Every element is positioned relative to a "containing block" — usually the parent element's content box, but sometimes the viewport or a positioned ancestor. Understanding containing blocks is crucial for positioning and percentage-based sizing.
<!-- Element with parent -->
<div class="parent">
<div class="child">Positioned relative to parent</div>
</div>
.parent {
width: 300px;
height: 200px;
position: relative; /* becomes containing block for children */
}
.child {
width: 50%; /* 50% of parent width (150px) */
height: 50%; /* 50% of parent height (100px) */
position: absolute; /* positioned relative to parent */
}
/* Without position: relative on parent, child relates to nearest positioned ancestor or viewport */
.without-position {
width: 300px;
height: 200px;
/* position: static (default) — NOT a containing block for positioned children */
}
.child-of-static-parent {
position: absolute; /* positioned relative to VIEWPORT, not parent */
}Flow vs out-of-flow elements
Elements can be "in flow" (part of the normal layout) or "out of flow" (removed from normal layout and positioned independently).
/* In flow — participates in normal layout */
.in-flow {
display: block;
/* Element takes up space in the layout */
}
/* Out of flow — removed from normal layout */
.out-of-flow {
position: absolute;
/* Element doesn't take up space, positioned independently */
}
.also-out-of-flow {
position: fixed;
/* Positioned relative to viewport, not affected by other elements */
}
.float-out-of-flow {
float: left;
/* Removed from normal flow, but text can wrap around it */
}Layout methods comparison
/* NORMAL FLOW — default, mostly automatic */
.normal-flow {
display: block;
/* Browser handles positioning */
}
/* POSITIONING — manual control */
.positioned {
position: absolute;
top: 50px;
left: 100px;
/* You specify exact position */
}
/* FLEXBOX — one-dimensional with auto distribution */
.flex-container {
display: flex;
justify-content: space-between; /* distribute items */
/* Great for menus, toolbars, component layouts */
}
/* GRID — two-dimensional with auto placement */
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* Great for page layouts, dashboards */
}
/* FLOATS — legacy one-dimensional (avoid for new layouts) */
.float {
float: left;
width: 300px;
/* Old way before flexbox/grid */
}