Topic 5.4
The display Property
In one line
display decides what kind of box an element makes: a block that takes a full row, an inline box that flows inside text, an inline-block mix of both, no box at all (none, contents), or a block that contains its own layout (flow-root).
Think of it like this
Furniture and words on a page. A block is like a bookshelf: it takes a whole wall to itself, and the next shelf goes below it. An inline box is like a word in a sentence: it sits next to other words and wraps to the next line when the line is full. An inline-block is like a sticker in a sentence: it sits in the line like a word, but it has its own fixed size.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- display
- The CSS property that decides what kind of box an element makes and how its children are laid out.
- Block box
- A box that starts on a new line and fills the full width of its parent, like a paragraph.
- Inline box
- A box that flows inside a line of text, like a word. It ignores width and height.
- inline-block
- A box that sits in a line like a word but can have its own width, height and vertical spacing.
- Baseline
- The invisible line that letters sit on. Letters like g and y hang below it.
- display: none
- Remove the element and its children completely: no box, no space, not read by screen readers.
- display: contents
- Remove the element's own box but keep its children, which act as children of its parent.
- Outer and inner display
- Outer: how the box sits among its siblings (block or inline). Inner: how it lays out its children (flow, flex, grid…).
Step by step
01See the defaults
Write a paragraph containing a link and a <strong> word. The paragraph is block (full width, its own line); the link and the strong word are inline (they flow with the text). You haven't written any CSS: the browser's default stylesheet set these.
<p>Read the <a href="#">guide</a> before you <strong>start</strong>.</p>02Try to size an inline box
Give the link width: 200px; height: 50px. Nothing changes: inline boxes ignore width and height. Add padding: 20px and the background grows up and down over the neighbouring lines, but the lines don't move apart.
03Switch it to inline-block
Add display: inline-block. Now the width, height and vertical padding all work, the line grows to fit it, and it still sits inside the sentence.
a {
display: inline-block;
width: 200px;
padding: 8px;
}04Hide things three different ways
display: none removes it and its space. visibility: hidden keeps the space but shows nothing. display: contents removes only the wrapper's own box and keeps the children.
05Contain a float with flow-root
A floated image (Topic 6.4) inside a short box hangs out of the bottom of its parent, because floats don't add to the parent's height. display: flow-root on the parent makes it grow to contain the float.
.media {
display: flow-root; /* contains the floated .thumb */
}
.thumb {
float: left;
}Try it yourself
- 1
Turn the span into a block
In the first example, add
display: blockto.inl. Predict: does it now take 200px, and does it still sit in the sentence? (It uses the width, but breaks the sentence: a block always starts a new line.) - 2
Swap visibility and display
In the second example, change
.ghosttodisplay: none. Predict the second log line before running. - 3
Remove flow-root
In the third example, delete the
.rootrule. Both lines should now printfalse, and the two orange squares stack strangely.
Code & diagrams
The parent's content area is 300px wide (its 1px border sits outside that), and the block fills all of it. The inline span ignores width and height; the inline-block uses them (plus 6px padding on each side).
Preview
Console
Nothing logged yet.Expected console output
block div fills its parent: 300
inline span uses width 200? false
inline-block outer width: 212
inline-block outer height: 52Look at the preview: a 44px blank gap for the hidden box, no border around the pink text, and the first box is gone entirely.
Preview
Console
Nothing logged yet.Expected console output
display: none height: 0
visibility: hidden height: 44
display: contents box height: 0
its child still shows: truePreview
Console
Nothing logged yet.Expected console output
plain contains the float: false
root contains the float: trueBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Give a link a height
Write nav a { height: 48px; width: 120px; background: navy; color: white; } for a row of navigation links.
Break #2
Gaps between inline-block cards
Put four inline-block cards with width: 25% on separate lines in the HTML.
Break #3
display: contents on a button
Set display: contents on a <button> to remove its box from a grid.
Myth vs fact
Myth
An element's tag decides if it's block or inline.
Fact
The tag only sets the browser's default display. CSS can make a span a block and a div inline. What's fixed is the HTML content model (what may go inside what), not the box type.
Myth
display: none and visibility: hidden are the same.
Fact
none removes the box and its space; visibility: hidden keeps the space. Both hide the element from screen readers. A child of a visibility: hidden parent can be shown again with visibility: visible; a child of a display: none parent can't.
Myth
Inline elements can't have padding.
Fact
They can, and it's painted, but vertical padding doesn't push other lines away. Horizontal padding does take space in the line.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The multi-keyword syntax (
display: inline flex,display: block flow-root) is supported in all major browsers since 2023. The one-word values remain valid and are what most code uses. - ▸
display: noneelements are skipped by layout and paint, and by the accessibility tree. For content that should be hidden visually but read by screen readers, use a "visually hidden" class (clip it to 1px) instead; for content hidden from everyone but kept rendered for speed, look atcontent-visibility: hidden. - ▸
Changing
displaytriggers layout. Toggling betweennoneand something else is cheap for small elements but expensive for large subtrees, because the whole subtree is built or torn down. Note too thatdisplaycan't be smoothly transitioned in older browsers; newer ones supporttransition-behavior: allow-discretefor that. - ▸
The HTML
hiddenattribute is implemented in the default stylesheet asdisplay: none. A CSS rule like.card { display: flex }overrides it, so the element shows despitehidden. Many resets add[hidden] { display: none !important; }.
Remember this
- 1
display: blockboxes start on a new line, stretch to fill the full width of their parent (unless you give them awidth), and stack top to bottom. They respectwidth,height, and all margins and padding.div,p,h1–h6,ul,sectionandformare block by default (the browser's built-in stylesheet sets that). - 2
display: inlineboxes sit inside a line of text, side by side, and are only as wide as their content. They **ignorewidthandheight. Their left and right padding, border and margin push neighbours sideways, but their top and bottom padding and margin don't move other lines**: vertical padding and borders are painted (they may overlap the line above or below) yet take no space.span,a,strong,emandcodeare inline by default. - 3
display: inline-blockboxes sit in a line like inline boxes, but inside they behave like blocks:width,height, and vertical padding and margin all work and push other lines away. They are useful for buttons, badges and tags in a sentence. One gotcha: the whitespace (spaces and line breaks) between inline-block elements in your HTML becomes a visible gap, and inline-blocks sit on the text baseline, leaving a few pixels below them for letters like g and y. - 4
display: noneremoves the element and everything inside it from the page entirely: no box, no space, not clickable, and hidden from screen readers. Comparevisibility: hidden, which hides the element but keeps its space.display: contentsdoes something different again: the element's own box disappears (no background, border, padding or size), but its children stay and act as if they were children of the element's parent. It's handy for making a wrapper invisible to a flex or grid layout. - 5
display: flow-rootmakes a normal block box that also starts a new block formatting context (BFC, see Topic 5.3). That means it fully contains floated children (its height grows to wrap them) and its children's margins can't collapse through it. It was added to CSS exactly for this, replacing old hacks like the "clearfix" (Topic 6.4 — Floats) andoverflow: hidden. - 6
displayreally sets two things: the outer type (how the box takes part in its parent's layout:blockorinline) and the inner type (how its children are laid out:flow,flow-root,flex,grid,table). Modern CSS lets you write both:display: block flowisblock,display: inline flow-rootisinline-block, anddisplay: inline flexisinline-flex. The one-word values you know are shortcuts. Flexbox (Phase 7) and Grid (Phase 8) aredisplayvalues too.
Explain it without notes
What are the differences between block, inline and inline-block boxes?
Compare display: none, visibility: hidden and display: contents.
What problem does display: flow-root solve?
What do the outer and inner display types mean? Give examples.
Practice
Make three <a> tags look like 120px-wide, 40px-tall buttons in a row, without Flexbox. Log the offsetWidth of the first.
A .list wrapper must disappear from layout while its three .item children stay. Log the wrapper's getBoundingClientRect().height and the number of visible items.
Trade-offs
- ↔
inline-blockwas the old way to put boxes in a row; it works everywhere but brings whitespace gaps and baseline alignment. Flexbox and Grid replace it for layout; keep inline-block for things that truly sit in text. - ↔
display: contentsmakes wrappers disappear from layout, which helps flex and grid, but you lose the wrapper's background, border and padding, and must test accessibility on semantic elements.
Done when you can
I can say how block, inline and inline-block boxes differ.
I can choose between
display: none,visibility: hiddenanddisplay: contents.I can use
flow-rootto contain floats and stop margin collapse.I can explain the whitespace gap between inline-block elements.
I can read two-value display syntax like
inline flex.