ForgeFrontend — Prepare, Practice, Crack
Secure checkout
Lifetime access
Instant PDF download
Free updates forever

Prepare · Practice · Crack

inline vs block vs inline-block in CSS

Short answer

A block element starts on a new line and fills the available width. An inline element sits inside the line of text and ignores width, height and vertical margins. inline-block sits in the text flow like inline but accepts width, height and margins on all four sides like block.

blockinlineinline-block
Starts a new lineYesNoNo
Default widthFills the containerFits the contentFits the content
width / height respectedYesNoYes
Vertical margin respectedYesNoYes
Horizontal margin respectedYesYesYes
Padding pushes siblings apartAll sidesHorizontally onlyAll sides
Affected by text-alignNo — it aligns its contentYes — it is contentYes — it is content
Default fordiv, p, h1–h6, sectionspan, a, strong, em, img*Nothing — you opt in
Three display values, four behaviours that actually differ.

The one rule that explains all three

Every element in a CSS layout is either taking part in the flow of text or interrupting it. Inline elements are part of a line — the browser lays them out left to right, wrapping when the line runs out, exactly like words. Block elements interrupt: they break the line, take a rectangle of their own, and stretch to fill whatever width their container offers.

That split explains every difference in the table. An inline element cannot have a height because a line box already has a height, determined by the font. It cannot have a vertical margin because pushing a word up or down would break the line it belongs to. inline-block is the deliberate hybrid: from the outside it behaves like a word, from the inside it behaves like a box.

The same three spans, three display valueshtml
1<style>
2  span { width: 200px; height: 60px; margin: 20px; background: #1A2333; }
3  .a { display: inline; }
4  .b { display: block; }
5  .c { display: inline-block; }
6</style>
7
8<p>Text <span class="a">inline</span> continues on the same line.</p>
9<!-- → width, height and the 20px vertical margin are all ignored -->
10
11<p>Text <span class="b">block</span> is pushed onto its own line.</p>
12<!-- → 200×60 box, 20px margin all round, line broken before and after -->
13
14<p>Text <span class="c">inline-block</span> stays in the line.</p>
15<!-- → 200×60 box with full margins, but the sentence flows around it -->

inline vs inline-block: the pairing people search for most

This is the comparison that actually matters day to day, because both keep the element in the text flow and it is easy to assume they are interchangeable. They are not. inline ignores width, height, margin-top and margin-bottom entirely. Set them and nothing happens — no warning, no error, just a declaration the browser discards.

The declarations inline throws awaycss
1a.button {
2  display: inline;      /* the default for <a> */
3  width: 160px;         /* → ignored */
4  height: 44px;         /* → ignored */
5  margin: 12px 0;       /* → the 12px top/bottom is ignored, left/right works */
6  padding: 12px 24px;   /* → applied, but see the overflow problem below */
7}
8
9a.button {
10  display: inline-block;
11  width: 160px;         /* → 160px */
12  height: 44px;         /* → 44px */
13  margin: 12px 0;       /* → 12px above and below, as written */
14}

The practical rule: the moment you want to give something a size or space it vertically, it can no longer be inline. Nav links, buttons made from anchors, chips and badges are all cases where the default inline behaviour is wrong and inline-block is the minimum fix.

Padding that overlaps, and the fixcss
1.highlight {
2  display: inline;
3  padding: 10px;
4  background: #F97316;
5}
6/* → the orange background bleeds over the line above and below,
7     because the line box height still comes from the font alone */
8
9.highlight {
10  display: inline-block;
11  padding: 10px;
12}
13/* → the line grows to fit; neighbouring lines are pushed away */

block vs inline: what "fills the width" really means

A block element's width is `auto` by default, and auto means "whatever is left" — it expands to fill its containing block regardless of how little content it holds. An empty div with a background colour still paints a full-width stripe. An inline element's width is always the width of its content; there is no such thing as an empty inline element taking up space.

This is why a div wrapped around a short label stretches across the page, and why the usual instinct — setting a width — is often the wrong fix. If you want the box to shrink to its contents while staying on its own line, `width: fit-content` says that directly, and keeps the element a block for margin purposes.

Three ways to stop a block filling the widthcss
1.tag { display: block; }
2/* → full container width, even for the word "New" */
3
4.tag { display: block; width: fit-content; }
5/* → shrinks to the text, still on its own line, margin: auto still centres it */
6
7.tag { display: inline-block; }
8/* → shrinks to the text AND sits in the text flow */
9
10.tag { display: block; width: 80px; }
11/* → 80px whatever the text is: truncates or overflows when it changes */

This is 1 of 200+ questions in the Complete Frontend Kit

Get every question with detailed answers, follow-ups and real code — plus coding challenges and a last-minute revision sheet. One-time payment, instant access.

⚡ Get the Complete Frontend Kit → ₹499

The whitespace gap nobody expects

Because inline-block elements participate in the text flow, the whitespace between them in your HTML is rendered as an actual space — usually about 4px at a 16px font size. Lay out four cards as inline-block, each 25% wide, and they will not fit on one line. Nothing in your CSS explains the extra pixels, which makes this one of the most frustrating bugs a beginner meets.

Where the mystery 4px comes fromhtml
1<div class="cards">
2  <div class="card">A</div>
3  <div class="card">B</div>
4</div>
5<!-- .card { display: inline-block; width: 50%; }
6     → the newline between the divs is a space, so 50% + 4px + 50%
7       overflows and B wraps to the next line -->
8
9<!-- Fix 1: remove the whitespace from the markup -->
10<div class="cards"><div class="card">A</div><div class="card">B</div></div>
11
12<!-- Fix 2: comment the gap away -->
13<div class="cards">
14  <div class="card">A</div><!--
15--><div class="card">B</div>
16</div>

Both of those fixes work and both are unpleasant, because they make your HTML formatting load-bearing. The historical CSS workaround — `font-size: 0` on the parent, restored on the children — has its own problems with inherited units. In 2026 the honest answer is that if you are fighting whitespace gaps, you wanted flexbox.

The fix that actually belongs in modern codecss
1.cards {
2  display: flex;
3  gap: 16px;          /* → real, controllable spacing */
4}
5.card { flex: 1; }    /* → equal columns, no whitespace artefacts */
6
7/* The legacy workaround, for context — you will see it in old code */
8.cards { font-size: 0; }
9.card  { display: inline-block; font-size: 1rem; }
10/* → gap gone, but every unstyled child now inherits font-size: 0 */

Is inline-block obsolete now that flexbox exists?

For layout, largely yes. Rows of cards, navigation bars, toolbars and equal-width columns were the classic inline-block use cases, and flexbox does all of them better with real gap control, alignment and wrapping. Reaching for inline-block to build a row in new code is a mild signal that you learned CSS from an older tutorial.

But inline-block still has a job flexbox cannot do: putting a sized box inside a line of text. A flex container makes every child a flex item and takes them out of the text flow entirely. When you want a badge that flows with a sentence and wraps with it, inline-block is exactly right and there is no modern replacement.

You want…Use
A row of cards or columnsflex or grid
A navigation barflex
A sized badge inside a sentenceinline-block
An icon aligned with textinline-block, or inline-flex
A link that needs a click target of 44pxinline-block with padding
A full-width sectionblock (the default)
Centring one box horizontallymargin-inline: auto on a block
What to reach for, in code written today.

Alignment: the part that catches people out

inline-block elements sit on the text baseline by default, not at the top of their line. Put two inline-block boxes of different heights next to each other and the shorter one appears to float, because both are aligned by the baseline of their last line of text. This is correct behaviour for something in a text flow, and almost never what you wanted for a row of cards.

vertical-align only works on inline-level boxescss
1.card { display: inline-block; vertical-align: top; }
2/* → tops line up, which is what a card row needs */
3
4.icon { display: inline-block; vertical-align: middle; }
5/* → centres the icon against the text's midline */
6
7.wrapper { display: block; vertical-align: middle; }
8/* → ignored entirely: vertical-align does nothing on a block element,
9     which is why it is one of the most misapplied properties in CSS */

The other half of the confusion is `text-align`. It aligns the inline content inside a block, so setting it on the box you want to move does nothing — you set it on the parent. A block element cannot be moved by text-align at all, because it is not inline content; you centre a block with auto margins.

The display values you will also meet

The three in this comparison are the classic ones, but a handful of others come up often enough to be worth recognising, especially since CSS now describes display as two values — how the box behaves outside, and how it lays out its children inside.

ValueBehaves likeNotes
noneRemovedNot rendered, no space, invisible to screen readers
inline-flexinline outside, flex insideA flex container that sits in a line
inline-gridinline outside, grid insideSame idea for grid
flow-rootblockContains its floats — a clean clearfix
contentsNothingThe box disappears; children promote to the parent
list-itemblock + markerWhat li uses by default
The rest of the display keywords, briefly.

`display: none` deserves a specific warning because it is often used for things that should still be reachable. It removes the element from the accessibility tree entirely, so a screen reader user cannot find it. For something visually hidden but still announced — a label, skip link or live region — use a clip-based utility class instead.

Why is there a gap under my image?

Images are inline by default, so they sit on the text baseline and the browser reserves the font's descender space below them — usually 3–5px. Setting display: block on the image removes it, and so does vertical-align: bottom. It is the same baseline rule that causes the inline-block whitespace gap.

Can an inline element contain a block element?

The HTML parser allows it in some cases — an <a> wrapping a <div> is valid HTML5 — but the rendering is awkward: the browser splits the inline box around the block, which can produce strange borders and backgrounds. Where you need a clickable card, set display: block on the anchor rather than nesting a block inside an inline box.

Does display change how an element behaves inside flexbox?

It is overridden. A flex container blocks its children's outer display value entirely — every direct child becomes a flex item and is laid out as a block-level box, whatever you set. Writing display: inline-block on a flex child has no effect, which surprises people debugging a layout.

What is the difference between visibility: hidden and display: none?

visibility: hidden keeps the element's box in the layout — the space stays reserved and neighbours do not move — while display: none removes the box entirely and everything reflows. Both hide the element from screen readers; only display: none changes the layout.

Why does my <a> not respond to width?

Because anchors are inline by default, and inline elements ignore width. Set display: inline-block or block on it. This is the single most common version of this question in real work, usually while trying to give a nav link a 44px minimum tap target.

Frequently asked questions

What is the difference between inline, block and inline-block in CSS?
block elements start on a new line and fill the container's width. inline elements sit inside the line of text, size themselves to their content, and ignore width, height and vertical margins. inline-block stays in the text flow like inline but accepts width, height and margins on all four sides like block.
What is the difference between inline and inline-block?
Both keep the element in the text flow, but inline discards width, height, margin-top and margin-bottom, while inline-block honours all of them. If you need to size something or space it vertically and it must stay in a line of text, inline-block is the one you want.
What is the difference between block and inline-block?
block breaks the line before and after itself and stretches to the container's width by default. inline-block sits alongside other content on the same line and shrinks to fit its contents. Both respect the full box model, so the difference is line-breaking and default width, not sizing.
When should I use inline-block?
When a sized box has to sit inside a line of text — a badge in a sentence, an icon beside a label, an anchor that needs a proper tap target. For rows of cards or navigation layouts, flexbox is the better tool and avoids the whitespace gap entirely.
Why does width not work on my span or link?
Because span and a are inline by default, and inline elements ignore width and height. Add display: inline-block to keep it in the text flow while making it sizeable, or display: block if it should also take its own line.
Why is there a gap between my inline-block elements?
The whitespace between them in the HTML — a newline or a space — is rendered as an actual space character, roughly 4px at a 16px font size. Remove the whitespace from the markup, comment it out, or switch the container to flexbox with gap, which is the modern fix.
Does padding work on inline elements?
Horizontal padding works normally. Vertical padding is applied but does not increase the line box's height, so the background paints over the lines above and below instead of pushing them apart. Use inline-block if you need vertical padding to affect layout.
Is inline-block still needed now that we have flexbox?
For layout, rarely — flexbox and grid handle rows, columns and navigation better. inline-block still has one job nothing else does: putting a sized box inside a line of text so it flows and wraps with the sentence. A flex container would pull it out of that flow.
Which HTML elements are block by default?
div, p, h1 through h6, section, article, header, footer, nav, ul, ol, li, form and table, among others. span, a, strong, em, img, input, label, code and small are inline by default. You can override any of them with the display property.
Why is there a gap below my image?
Images are inline, so they sit on the text baseline and the browser leaves room for the font's descenders underneath — usually 3 to 5 pixels. Set display: block on the image, or vertical-align: bottom, and the gap disappears.
How do I centre an inline-block element?
Set text-align: center on its parent, because an inline-block is inline content as far as the parent is concerned. Setting text-align on the element itself only centres the text inside it. A block element centres with margin-inline: auto and an explicit width instead.
What is the difference between inline-block and inline-flex?
Both sit in the text flow like inline-block. The difference is inside: inline-flex lays its children out as a flex container, giving you alignment and gap, while inline-block lays them out in normal flow. inline-flex is usually the better choice for a chip containing an icon and a label.

This is 1 of 200+ questions in the Complete Frontend Kit

Get every question with detailed answers, follow-ups and real code — plus coding challenges and a last-minute revision sheet. One-time payment, instant access.

⚡ Get the Complete Frontend Kit → ₹499
Written by Arun Karthikeyan · Last updated

Full kit

Complete Frontend Kit · ₹499

Get it →