Block, Inline, and the Normal Flow
Before any layout system, the browser already has one, and half of learning CSS layout is understanding what it does by default. Find out why width does nothing on a span and why an image leaves a gap underneath it.
Worth reading first: Every Element Is a Box With Four Layers
Before any layout system, the browser already has one, and half of learning CSS layout is understanding what it does by default. Find out why width does nothing on a span and why an image leaves a gap underneath it.
Normal flow is a layout you did not ask for
Write a page with no CSS and the content still arranges itself: headings and paragraphs stack down the page, words run left to right and wrap at the edge. That is normal flow, and every layout technique in the next chapters is a modification of it rather than a replacement.
Normal flow has two directions running at once, and the difference between them is the whole of this chapter.
Block direction — down
Block-level boxes stack vertically, each on a new line, each filling the available width. Headings, paragraphs, sections, lists.
Inline direction — across
Inline boxes sit in a line of text, side by side, wrapping to a new line when they run out of room. Links, spans, strong, images.
Block elements take the whole line
A block element starts on a new line and takes the full width of its container, whatever its content actually needs. A three-word heading still occupies the whole row.
div p h1–h6 section article header footer nav mainul ol li form figure blockquote table hrAlways starts on one, and the next element starts on another.
Fills the container by default, regardless of content.
Both respected.
Respected, and vertical ones collapse — chapter 14.
Inline elements ignore width and vertical margin
An inline element is part of a line of text. It is as wide as its content, sits alongside its neighbours, and — this is the part that catches everyone — ignores width and height entirely.
Some text before. OneTwoThree Some text after.
width: 120px is
respected
margin: 8px is
respected on all four sides
Takes the whole line, every time
A block element starts on a new line and fills the available width unless you say otherwise. div, p, h1–h6, section, ul, li — the structural elements. Setting width makes it narrower, and it still refuses to share the line.
Switch to inline and watch the boxes collapse to the width of their text while the CSS still clearly says width: 120px. Nothing warns you. Devtools shows the declaration applied and not crossed out, because it is applied — it simply has no meaning for this display type.
Switch that to inline and watch the boxes collapse to the width of their text while the CSS still says width: 120px. Nothing warns you, and devtools shows the declaration applied and not crossed out — because it is applied. It simply has no meaning for this display type.
Ignored. This is the answer to "why is my width not working", and it is nearly always a span or an a.
Ignored. Top and bottom margins do nothing at all.
Renders — the background extends — but does not push the surrounding lines apart. It overlaps them instead.
Both respected normally.
inline-block is the compromise
display: inline-block flows inline with its neighbours and behaves like a block on the inside: width, height, and vertical margins all work.
.tag { display: inline-block; padding: 0.25rem 0.75rem; margin-bottom: 0.5rem; /* works — would be ignored if inline */ border-radius: 999px; background: #dbefdb;}For a decade this was how you laid out a row of anything. Flexbox does that job better now, and inline-block remains right for something that genuinely belongs within a line of text — a tag, a badge, a small button inside a sentence.
The other display values you will meet:
The children become flex items, laid out in one dimension. Chapter 17.
The children become grid items, in two dimensions. Chapter 18.
The same, but the container itself sits inline.
A block that contains its children's margins and floats. The modern answer to a problem people used to call clearfix.
display: none versus visibility: hidden
Three ways to hide something, with three different consequences. Picking the wrong one is an accessibility bug rather than a visual one.
Removed from the layout entirely. Takes no space, is not read by screen readers, is not focusable. The right answer for genuinely hidden content.
Invisible but STILL OCCUPIES ITS SPACE. Not announced, not focusable. Right when you need the layout to stay put.
Fully transparent, still occupies space, and is STILL FOCUSABLE AND ANNOUNCED. A keyboard user can tab into something nobody can see.
Invisible on screen, still read by screen readers. For text that gives context to assistive technology only.
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;} /* <a href="/cart">Cart <span class="visually-hidden">(3 items)</span></a> */That pattern is standard, it appears in essentially every design system, and it is the correct way to add context for screen readers without changing the visual design.
Key takeaways
- Normal flow is a layout you already have: blocks stack down, inline content runs across and wraps.
- Layout techniques modify normal flow rather than replacing it, and its default is already the small-screen answer.
- Block elements start on a new line, fill the width, and respect width, height, and all four margins.
- Inline elements ignore width, height, and vertical margins entirely — this is why "my width does nothing".
- Vertical padding on an inline element renders but does not push other lines away; it overlaps them.
- The gap under an image is baseline space for descenders. display: block or vertical-align: middle removes it.
- inline-block flows inline and honours width, height, and vertical margins — right for badges inside a sentence.
- inline-block has a whitespace gap between items because the newline in your HTML is a space. Flexbox does not.
- display: none removes it from layout and from screen readers; visibility: hidden keeps the space.
- opacity: 0 keeps it focusable and announced — a keyboard user can tab into something invisible.
- The .visually-hidden pattern hides something on screen while keeping it available to screen readers.
Quick check
Answer these to unlock the next chapter — 3 of 4 to pass. You can retake it anytime.
Answer every question to check.
Make a free account to read on
Every chapter is free — an account is how your progress, XP, and streak follow you from your laptop to your phone, and how you show up on the leaderboard. No payment, no trial.