Skip to content

Display ​

Some boxes stack like shelves. Others flow like words in a sentence. The display property decides which.

Have you tried giving a link a width yet, and watched absolutely nothing happen? Or added margin-top to a <span> and seen no gap appear? It's baffling the first time. You're writing perfectly good CSS and the browser is just... ignoring you.

It isn't ignoring you. It's following the rules of display, and once you know them, all of that behavior makes sense.

Shelves and books, again ​

Back in Nesting and the DOM, we talked about block elements as shelves and inline elements as books sitting on those shelves. That wasn't just a metaphor for HTML. It's exactly what the CSS display property controls.

display: block: the shelf ​

css
.shelf {
	display: block;
}

Block boxes, like <p>, <h1>, <div>, <section>, and <li>:

  • start on a new line,
  • stretch to fill the full width of their container by default,
  • respect width, height, margin, and padding on every side.

A shelf takes up the whole wall, and the next shelf goes underneath it.

display: inline: the words ​

css
.word {
	display: inline;
}

Inline boxes, like <a>, <span>, <strong>, and <em>:

  • sit in the line of text, flowing along like words in a sentence,
  • are only as wide as their content,
  • ignore width and height (images are the exception: they sit in the line of text, but still take a size),
  • have padding and margin on the left and right that push neighbors away, but top and bottom margins that do nothing to the lines around them.

That last point is the one that catches everyone. Why would the browser ignore a vertical margin? Think about a word in the middle of a paragraph. If one word could push itself 40px downward, it would tear the line apart. Inline boxes follow the line, and the line decides the height. Their vertical padding is painted (the background grows), but it just overlaps the lines above and below instead of moving them.

display: inline-block: the Scrabble tile ​

css
.tag {
	display: inline-block;
	padding: 4px 12px;
	margin: 4px;
	border-radius: 999px;
	background: #d8e7ef;
}

What if you want something that sits in a line, like a word, but has a proper solid size, like a box? Think of Scrabble tiles on a rack: they sit side by side in a row, but each one is a sturdy little square with its own dimensions.

That's inline-block. It flows in the line like inline, and it respects width, height, padding, and margin like block. It's perfect for things like tags, badges, and buttons that sit in a row.

Changing an element's display ​

Here's the important part: display is a style, not a meaning. You can change it on any element:

css
nav a {
	display: block;      /* each link fills its row, making a bigger click area */
}

.menu li {
	display: inline-block;  /* list items side by side instead of stacked */
}

The <a> is still a link, and the list is still a list, as far as HTML and screen readers are concerned. You've only changed how it's arranged on screen. That's the separation of structure and presentation from What CSS Is and Why It Exists in action: choose the element for its meaning, then choose its display for the layout.

Hiding things: none vs hidden ​

css
.sold-out-banner {
	display: none;
}

.placeholder {
	visibility: hidden;
}

Both make an element disappear, but very differently. Picture a chair in a room:

  • display: none carries the chair out of the room. It's gone. Everything else shifts to fill the empty space. Screen readers don't see it either.
  • visibility: hidden throws a magic invisibility sheet over the chair. You can't see it, but it's still taking up floor space, so nothing moves.

Use display: none when something truly shouldn't be there right now, like a closed menu. Use visibility: hidden when you need to keep the space reserved so the layout doesn't jump.

Both of them also hide the element from screen readers.

(Remember the HTML hidden attribute from Attributes Deep Dive? Under the hood, the browser applies display: none to it. That's also its catch: your own rule, like .card { display: flex; }, beats it, and the "hidden" card shows up again. Many stylesheets add [hidden] { display: none !important; } to their reset to keep hidden reliable.)

Hidden from eyes, available to screen readers ​

Sometimes you want the opposite of visibility: hidden: text that screen readers announce but sighted visitors don't see, like "(opens in a new tab)" next to an icon. That's the visually hidden pattern, a small utility class found in almost every professional stylesheet:

css
.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

It shrinks the element to a single invisible pixel instead of removing it, so it stays in the accessibility tree.

The skip link from Accessibility Basics needs a variation of that idea: hidden until a keyboard user presses Tab, then visible:

css
.skip-link {
	position: absolute;
	top: 0.5rem;
	left: 0.5rem;
	z-index: 100;
	padding: 0.5rem 1rem;
	background: white;
	transform: translateY(-200%);   /* parked above the top of the page */
}

.skip-link:focus {
	transform: translateY(0);         /* slides into view on focus */
}

Being position: absolute, it never takes up room in the page's layout, whether it's showing or not. That matters for the page layouts in Common Layout Patterns.

Overflow: an overstuffed suitcase ​

Sometimes content is bigger than its box. A long word in a narrow column. A tall list in a short container. What happens then?

css
.box {
	height: 120px;
	overflow: auto;
}

Think of a suitcase that's too full:

  • overflow: visible (the default): the clothes spill out over the sides. Content pokes out of the box and overlaps whatever's below.
  • overflow: hidden: you sit on the lid and force it shut. Anything that doesn't fit gets cut off and hidden.
  • overflow: auto: you add an expandable zip. A scrollbar appears only if it's needed.
  • overflow: scroll: the scrollbar is always there, needed or not.

Be careful with hidden. It's tempting as a quick fix, but it can chop off content people need, like the end of a sentence or a focus outline. auto is usually the safer choice.

One more thing: flex and grid are display values too ​

Here's a teaser. The two most powerful layout systems in CSS are switched on with... display:

css
.row {
	display: flex;
}

.gallery {
	display: grid;
}

Everything you've learned here is the old, basic flow of the page. flex and grid change the rules for the children of a box, and they make laying out rows, columns, and whole pages dramatically easier. You'll meet them properly in Flexbox: The Basics and CSS Grid: The Basics. First, though, one more tool: moving boxes around with Positioning and z-index.

Try it ​

CSS

Preview

Try it yourself ​

  1. Add display: inline-block; to .demo. Now the width and margin work.
  2. Change .gone from display: none to visibility: hidden. Chair 3 stays put, and there's an empty gap where Chair 2 was.
  3. Try overflow: hidden, then overflow: auto on the suitcase. Which one would you trust with real content?
  4. Notice the tags ignore their vertical margin. Make them inline-block and see the difference.

Check your understanding ​

Why does width have no effect on a plain a element?
What is the difference between display: none and visibility: hidden?
Which overflow value adds a scrollbar only when content does not fit?

Up next ​

Normal flow puts boxes in order, one after another. But what if you need to pin a badge to a corner, or keep a header on screen while you scroll? That's Positioning and z-index.

← Backgrounds, Borders, and Shadows
Positioning and z-index →

Answer the quiz above correctly to continue.