skip to content

Block and Inline Formatting Contexts

Normal flow is really two layout modes plus the contexts that isolate them. Knowing what establishes a block formatting context is the standard answer to float containment, margin-collapse prevention, and sidebar layouts.

part ofCSSoverview, primer and where to startread it →
on this pageshow

questions

4

In CSS, how do display: block, display: inline, and display: inline-block differ in the way width, height, and vertical margins apply to a box?

level: juniorimportance: must knowfreq 80%

answer

  1. two flow modes, not three
  2. outer role versus inner role
  3. inline boxes live inside line boxes
  4. width and height ignored on inline
  5. replaced elements are the exception

basics

~20 s

A block box takes a whole line and honours width, height and all four margins. A non-replaced inline box flows inside a line of text and ignores width, height and vertical margins. inline-block flows inline but sizes like a block.

solid answer

~50 s

Normal flow has two layout modes, and these three values pick which one a box uses on the outside and on the inside. `display: block` makes a box that starts on a new line and fills the inline space of its containing block; `width`, `height`, `margin`, `padding` and `border` all behave the obvious way. `display: inline` makes a box that is laid out inside a line box, next to text. On a non-replaced inline box such as a `<span>`, `width` and `height` are ignored outright and vertical margins have no effect at all; horizontal margins, padding and borders do apply, and vertical padding and borders still paint, they just don't push neighbouring lines apart, so they can overlap the line above. `display: inline-block` is the hybrid: outside it participates in the parent's inline formatting context, so it sits on the text baseline and is affected by surrounding whitespace, but inside it is a block container that honours width, height and vertical margins.

code

css · 22 lines
css
.block-box {
  display: block;
  width: 200px;
  height: 60px;
  margin: 24px 0;
}

.inline-box {
  display: inline;
  width: 200px;
  height: 60px;
  margin: 24px 8px;
  padding: 12px;
  border: 2px solid currentColor;
}

.inline-block-box {
  display: inline-block;
  width: 200px;
  height: 60px;
  margin: 24px 8px;
}

go deeper

for a junior

Be ready to say plainly that width and height do nothing on a plain inline element, that block boxes take a full line, and that inline-block is the one that flows inline while still being sizeable.

for a middle

Explain the outer/inner display model and the precise inline rules: vertical margins do not apply, vertical padding and borders paint but never grow the line box, and replaced elements are the exception because they carry an intrinsic size.

for a senior

Show judgment about when inline-block is the wrong tool: it drags in baseline alignment and source-whitespace sensitivity, so a flex or grid container is usually the better way to lay a row of sized boxes out.

for a principal

Own the consistency angle: decide whether components expose block-level boxes by default, and set the convention so contributors are not mixing inline-block rows, flex rows and grid rows for the same visual pattern across a large stylesheet.

## Normal flow is two modes, not three Every element in normal flow is laid out either as a **block-level box** stacked vertically in a *block formatting context*, or as an **inline-level box** placed horizontally into *line boxes* in an *inline formatting context*. The `display` property picks the box's **outer** role (how it participates in its parent) and its **inner** role (how it lays out its own children). `block` is outer block / inner flow; `inline` is outer inline / inner flow; `inline-block` is outer inline / inner flow-root — an inline-level box whose insides are a self-contained block layout. ## display: block A block box begins on a new line and, with `width: auto`, fills the inline size of its containing block. All four margins apply, vertical margins between siblings collapse under normal-flow rules, `width` and `height` resolve against the box-sizing model, and the box never sits beside text. Paragraphs, sections and list items are block-level by default in the user-agent stylesheet. ```css .card { display: block; width: 20rem; height: 8rem; margin: 1rem 0; /* all of this applies */ } ``` ## display: inline An inline box is dropped into the current line box among the text. Three consequences trip people up: 1. **`width` and `height` are ignored** on non-replaced inline boxes. The box is exactly as wide as its content. 2. **`margin-top` and `margin-bottom` have no effect.** They are not collapsed and not clamped — they simply do not apply to a non-replaced inline box. 3. **Vertical `padding` and `border` do apply and do paint**, but they do not contribute to the height of the line box. A `<span>` with `padding: 1em` will spill its background over the lines above and below rather than pushing them apart. Horizontal margins, padding and borders behave normally and displace the following text. An inline box can also **fragment**: if it wraps, it becomes several boxes, one per line, and horizontal borders appear only at the true start and end unless `box-decoration-break: clone` is set. ```css span.tag { width: 200px; /* ignored */ height: 40px; /* ignored */ margin: 20px 8px; /* only the 8px sides do anything */ padding: 4px 8px; /* paints, but the line box does not grow */ } ``` ## Replaced elements are the exception `<img>`, `<video>`, `<iframe>`, `<canvas>` and most form controls are **replaced elements**: their content comes from outside CSS and they carry an intrinsic size. They are inline-level by default, but `width` and `height` *do* apply to them, and so do vertical margins. That is why `img { width: 100px }` works while `span { width: 100px }` does nothing — the difference is replaced versus non-replaced, not something about the `display` value. ## display: inline-block `inline-block` was introduced for exactly the case where you want a box to sit in a line of text but still be sized. Its outer role is inline, so it is placed on the baseline of the line box and it responds to `text-align` and `vertical-align` on the parent. Its inner role is a block container that establishes its own formatting context, so `width`, `height`, vertical margins, padding and borders all work, its children lay out as blocks, and it does not fragment across lines — it moves to the next line whole. The cost of the inline outer role is that the box is still text-like: whitespace between two `inline-block` boxes in the source renders as a real space character, so the two boxes appear separated even with `margin: 0`, and the boxes align on their baselines rather than their edges. ```css .chip { display: inline-block; width: 6rem; height: 2rem; margin: 0.5rem; /* all of this applies */ } ``` ## The two-value syntax Modern CSS lets you spell the outer and inner roles explicitly: `display: block flow` is the classic `block`, `display: inline flow` is `inline`, and `display: inline flow-root` is exactly `inline-block`. The legacy single keywords remain valid aliases and are what you will see in nearly every codebase, but the two-value form makes the outer/inner model visible, which is the clearest way to reason about all three values. ## Choosing between them Use `block` for anything that owns a band of the page. Use `inline` for things that must flow with prose — emphasis, links, inline code. Reach for `inline-block` when a sized box genuinely belongs inside running text, such as a badge in a sentence. For laying a *row* of sized boxes out side by side, a flex or grid container is the better modern answer: it blockifies its children, so you get sizing without the baseline and whitespace behaviour that `inline-block` drags along.

  • So does padding-top on an inline span do literally nothing?
    It does something visually but nothing structurally. The padding is drawn, so the background and border extend upward, but the line box does not grow to accommodate it, so the padded area overlaps the line above. If you need the lines to move apart, increase `line-height` on the parent or make the box `inline-block`.
  • Why can you set height on an img but not on a span, when both are inline by default?
    Because `<img>` is a replaced element: its content comes from outside the CSS box model and it has an intrinsic width and height, so `width` and `height` apply to it even when it is inline-level. A `<span>` is non-replaced, so its inline box is sized purely by its content and both properties are ignored.
  • What does the two-value form display: inline flow-root correspond to?
    It is the explicit spelling of `inline-block`: outer display type `inline`, inner display type `flow-root`. The two-value syntax names the outer and inner roles separately, so `block flow` is `block` and `inline flow` is `inline`. It is supported across current evergreen browsers, and the legacy keywords remain valid aliases.

saying these in an interview costs you the question

  • Says inline boxes ignore padding entirely, including left and right
  • Claims width works on a span without changing display
  • Thinks vertical margins on an inline box collapse rather than not applying
  • Cannot explain why width works on an img but not a span
  • Describes inline-block as just a block that does not line-break

context

open as a page

In CSS, what is a block formatting context, and which declarations establish a new one?

level: seniorimportance: must knowfreq 58%

basics

~20 s

A block formatting context is a self-contained region of block layout: floats inside it are contained, outside floats cannot intrude, and margins cannot collapse through its boundary. overflow other than visible, display: flow-root, floats, absolutely positioned boxes, inline-blocks, table cells and flex or grid items each establish one.

open as a page

An image placed inside a div with no padding or margins still leaves a few pixels of space below it. Which CSS layout rule causes that gap, and what removes it?

level: middleimportance: should knowfreq 48%

basics

~20 s

The image is an inline-level box, so it sits on the text baseline of its line box, and the descender space reserved below that baseline shows as a gap. Set the image to display: block, or align it with vertical-align: bottom.

open as a page

Two boxes styled with display: inline-block sit side by side, but a few pixels of space appear between them even though both have margin: 0. In CSS, where does that gap come from and how do you remove it?

level: middleimportance: should knowfreq 55%

basics

~20 s

The gap is the whitespace between the two tags in the source. Inline-level boxes sit in an inline formatting context, so a newline or space collapses into one rendered space character sized by the parent's font. Remove the whitespace or stop using inline layout.

open as a page