Written by Rahul · Frontend Engineer at Google · Updated 2025
Every CSS layout problem starts here. If you don't understand block vs inline, you'll fight CSS forever. Let me break it down simply.
Block Elements
Block elements take up the full width available and start on a new line.
<div>I take full width</div>
<p>I also take full width</p>
<h1>Me too</h1>
/* Block elements by default: div, p, h1-h6, section, article, header,
footer, main, nav, ul, ol, li, form, table, blockquote */Block behavior:
- Takes full width of parent
- Starts on a new line
widthandheightwork ✅marginandpaddingwork in ALL directions ✅
Inline Elements
Inline elements only take up as much width as their content and flow within the text.
<p>This is <strong>bold</strong> and <em>italic</em> text.</p>
/* Inline elements by default: span, a, strong, em, img, input,
button, label, code, br, i, b, small, sub, sup */Inline behavior:
- Only takes width of content
- Flows in the same line as surrounding content
widthandheightare IGNORED ❌- Vertical
marginis IGNORED ❌ - Vertical
paddingworks visually but doesn't push other elements
Inline-Block — The Best of Both
.tag {
display: inline-block;
/* Now it flows inline BUT respects width/height/margin/padding */
padding: 4px 12px;
margin: 4px;
border-radius: 16px;
background: var(--accent);
}inline-block flows like inline but behaves like block for sizing. Perfect for tags, badges, and buttons.
The Classic Bugs
Bug 1: Why Won't My Span Take Width?
/* ❌ This won't work */
span.badge {
width: 100px;
height: 30px; /* Both ignored! span is inline */
}
/* ✅ Fix: Change display */
span.badge {
display: inline-block; /* or display: block */
width: 100px;
height: 30px;
}Bug 2: The Mysterious Gap Between Inline-Block Elements
/* ❌ Whitespace in HTML creates gaps */
<div class="item">A</div>
<div class="item">B</div>
.item { display: inline-block; width: 50%; }
/* These won't fit side by side — there's a ~4px whitespace gap! */
/* ✅ Fix 1: Use flexbox instead (recommended) */
.parent { display: flex; }
.item { width: 50%; }
/* ✅ Fix 2: Set font-size: 0 on parent */
.parent { font-size: 0; }
.item { font-size: 16px; }Bug 3: Vertical Margin Collapse on Blocks
/* Block elements have margin collapse */
.box1 { margin-bottom: 20px; }
.box2 { margin-top: 30px; }
/* Gap between them is 30px, NOT 50px — margins collapse to the larger value */
/* This doesn't happen with inline or inline-block elements */
/* Fix: use padding, or add overflow: hidden to parent */Modern Alternatives — Flexbox and Grid
/* In 2025, you rarely need inline-block for layout */
/* Use Flexbox for 1D layout */
.nav {
display: flex;
gap: 16px;
align-items: center;
}
/* Use Grid for 2D layout */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 24px;
}Quick Reference Table
| Property | block | inline | inline-block |
|---|---|---|---|
| New line | ✅ Yes | ❌ No | ❌ No |
| Full width | ✅ Yes | ❌ No | ❌ No |
| Width/Height | ✅ Works | ❌ Ignored | ✅ Works |
| Vertical margin | ✅ Works | ❌ Ignored | ✅ Works |
| Vertical padding | ✅ Works | ⚠️ Visual only | ✅ Works |
Best Practices
- Use Flexbox/Grid for layout — they replace most block/inline-block layout hacks
- Use
inline-blockfor small elements like tags, badges, icons - Don't set width/height on inline elements — change display first
- Remember margin collapse on block elements — use gap in Flex/Grid instead
- Use semantic HTML — browsers set the right display values for you