Block, inline and inline-block elements in HTML & CSS
display: block, display: inline, and display: inline-block control how elements occupy space and flow in the document.
Theory
TL;DR
- Block = full-page ads: takes the whole line, stacks vertically, respects all box model properties.
- Inline = words in a sentence: flows horizontally, ignores
width/height, only left/right margins apply. - Inline-block = images in text: flows inline but respects
width,height, and all margins. - Main difference: block forces line breaks and full width; inline ignores dimensions; inline-block allows both.
- Decision rule: block for layout sections, inline for text spans, inline-block for buttons or icons in a row.
Quick example
<style>
.block { display: block; background: lightblue; padding: 10px; margin: 10px; }
.inline { display: inline; background: lightgreen; padding: 10px; margin: 10px; }
.inl-block { display: inline-block; background: lightcoral; padding: 10px; margin: 10px; width: 120px; height: 50px; }
</style>
<!-- Stacks vertically, full width -->
<div class="block">Block 1</div>
<div class="block">Block 2 (below)</div>
<!-- Flows side by side, ignores width/height -->
<span class="inline">Inline 1</span>
<span class="inline">Inline 2</span>
<!-- Flows side by side, respects size -->
<span class="inl-block">Inline-block 1</span>
<span class="inl-block">Inline-block 2</span>Block elements stack. Inline elements sit beside each other but won't accept width or height. Inline-block sits beside each other and does accept sizing.
Key difference
Block triggers a line break before and after, then expands to fill the container width. That's why <div> takes the full row even if its text is one word. Inline joins the surrounding text flow like a word in a sentence: no line break, no response to width or height. Inline-block is the middle ground. It stays in the line flow but creates a sized box, which is why buttons typically work this way.
When to use
- Need something to stack vertically and fill width? Block. Sections, headers, article containers.
- Styling part of a sentence or wrapping a link inside text? Inline.
<span>,<a>,<em>. - Button, badge, or nav tab that needs padding and a fixed size but sits beside other elements? Inline-block.
- Avoid setting
widthorheighton inline elements - they have no effect.
Comparison table
| Property | block | inline | inline-block |
|---|---|---|---|
| Starts new line | Yes | No | No |
width / height respected | Yes | No | Yes |
| Margin (all sides) | Yes | Left/right only | Yes |
| Padding (all sides) | Yes | Left/right only | Yes |
| Full width by default | Yes | No | No |
| When to use | Sections, containers | Text styling | Buttons, badges, tabs |
Common mistakes
Setting width/height on inline elements:
span { display: inline; width: 200px; height: 100px; } /* both ignored */The browser ignores those properties on inline elements. Switch to inline-block if you need sizing.
Expecting vertical margins on inline elements:
<span style="margin-top: 20px;">Text</span>Vertical margins on inline elements don't affect layout. Only margin-left and margin-right work. Use inline-block or add vertical-align.
The whitespace gap with inline-block:
<span style="display: inline-block; width: 100px;">A</span>
<span style="display: inline-block; width: 100px;">B</span>The newline between the tags renders as a ~4px gap. I've seen this break nav layouts more than once. Fix: set font-size: 0 on the parent, or remove all whitespace between the closing and opening tags.
Real-world usage
- Bootstrap
btn-groupusesinline-blockfor side-by-side buttons (v5.3+). - GitHub's repo nav tabs are
inline-blocklinks with padding and borders. - Tailwind's
inline-blockutility appears in button and badge components. - Material UI's Chip component defaults to
inline-flex, which behaves the same way for line flow.
Follow-up questions
Q: What is the default display value of <img>?
A: Inline. Images are replaced elements that flow like text characters but keep their intrinsic dimensions. That's why there's often a small gap below an image inside a container - it's baseline alignment, not a bug.
Q: What happens to inline-block children inside a flex container?
A: The flex formatting context takes over. display: flex on the parent overrides the inline flow of its children. The width and height you set on those children still apply.
Q: Why does vertical-align only work on inline and inline-block elements?
A: It aligns elements within line boxes. Block elements create their own lines and have no line box to align against.
Q: (Senior) If you set display: block on a grid item, does it affect grid layout?
A: No. Grid items ignore their own display value for positioning because the grid formatting context takes over. But it does affect the item's internal formatting: its own children now flow as block. Mention the containing block concept here and you'll stand out.
Examples
Navigation bar with inline-block tabs
<nav style="background: #f6f8fa; padding: 1rem;">
<a href="#" style="display: inline-block; padding: 0.5rem 1rem; margin-right: 0.5rem;
background: white; border: 1px solid #ddd; text-decoration: none;">Code</a>
<a href="#" style="display: inline-block; padding: 0.5rem 1rem; margin-right: 0.5rem;
background: white; border: 1px solid #ddd; text-decoration: none;">Issues</a>
<a href="#" style="display: inline-block; padding: 0.5rem 1rem;
background: white; border: 1px solid #ddd; text-decoration: none;">Pull requests</a>
</nav>Each link needs padding and a border but must stay in one row. Pure inline would ignore padding dimensions in layout; block would stack each link on its own line. inline-block gives each link a proper box while keeping them side by side. This is the pattern behind GitHub's repo navigation.
User avatar with name
<style>
.avatar-wrap {
display: inline-block;
vertical-align: middle;
margin-right: 8px;
}
.avatar-wrap img {
display: block;
width: 32px;
height: 32px;
border-radius: 50%;
}
.username {
display: inline;
font-weight: bold;
}
</style>
<span class="avatar-wrap">
<img src="avatar.png" alt="User avatar">
</span>
<span class="username">john_doe</span>The image wrapper is inline-block so it can have a fixed size and vertical-align: middle to align with the text beside it. The username is plain inline because it needs no sizing - it flows as text.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.