The display property controls how an element's box behaves in the layout: whether it starts on a new line, whether width and height apply, and how its children are arranged. It is the switch that turns on Flexbox and Grid too.
Normal flow
Without any layout CSS, the browser places elements in normal flow. Each HTML element has a default display value from the browser stylesheet, and most are either block or inline.
<h2>Opening hours</h2>
<p>We are open <strong>every day</strong> from <a href="/hours">7am</a>.</p>
<h2> and <p> are block elements: each starts on a new line. <strong> and <a> are inline: they flow along inside the line of text.
display: block
Block boxes:
- Start on a new line and push the next element below.
- Fill the full available width by default.
- Respect
width,height,marginandpaddingon all sides.
Default block elements include div, p, h1 to h6, ul, li, section, article, header, footer and form.
display: inline
Inline boxes:
- Sit inside a line of text, next to their neighbours.
- Are only as wide as their content.
- Ignore
widthandheight. - Apply horizontal margin and padding, but vertical margins have no effect on the layout. Vertical padding is painted but does not push lines apart, so it can overlap the lines above and below.
Default inline elements include span, a, strong, em, code and img (images are a special case, called replaced elements, and do respect width and height).
a {
padding: 1rem; /* horizontal padding pushes text; vertical padding overlaps lines */
margin-top: 2rem; /* no effect */
width: 200px; /* no effect */
}
If width or margin-top "does nothing", inspect the element in DevTools and check its computed display. An inline element is the usual culprit. Chrome shows a hint icon next to properties that have no effect for this reason.
display: inline-block
inline-block is a hybrid. The element sits in the line like inline text, but accepts width, height and vertical spacing like a block:
<p>
<a class="button" href="/order">Order now</a>
<a class="button" href="/menu">See the menu</a>
</p>
.button {
display: inline-block;
padding: 0.75rem 1.25rem;
margin-block: 0.5rem;
background-color: #0b5394;
color: white;
text-decoration: none;
border-radius: 0.375rem;
}
The two links sit side by side, but their padding now takes up space, so they no longer overlap the lines around them.
| Behaviour | block | inline | inline-block |
|---|---|---|---|
| Starts on a new line | Yes | No | No |
| Default width | Full available width | Content width | Content width |
width and height apply | Yes | No | Yes |
| Vertical margin affects layout | Yes | No | Yes |
The gap between inline-blocks
Inline-block elements are treated like words, so the whitespace between them in your HTML becomes a visible space. That is fine for buttons in a sentence. For laying out a row of boxes it is a nuisance, and one reason Flexbox replaced inline-block for most layouts.
Changing the default
display changes how an element looks and flows, never what it means. A <span> can become a block and a <li> can become inline:
.nav-list li {
display: inline-block;
}
.error-message {
display: block;
}
A <span> styled as a block is still a span to screen readers and search engines. Choose HTML for meaning, then use display for layout.
display: none
display: none removes the element from the page entirely. It takes up no space, and screen readers do not announce it.
.is-hidden {
display: none;
}
Compare with visibility: hidden, which hides the element but keeps its space:
| Technique | Visible | Takes space | Announced by screen readers |
|---|---|---|---|
display: none | No | No | No |
visibility: hidden | No | Yes | No |
opacity: 0 | No | Yes | Yes |
opacity: 0 hides content visually, but it is still there for keyboard and screen reader users, who may tab into an invisible link. For content that should be hidden from everyone, use display: none or the HTML hidden attribute. To hide something visually but keep it for screen readers, use a dedicated visually-hidden class, explained in the Web Accessibility Essentials course.
display: flow-root
flow-root makes a block that contains its children's margins and floats. You saw it in the box model lesson as a fix for margin collapsing:
.banner {
display: flow-root;
}
A first look at flex and grid
display also has two values that change how an element lays out its children:
.toolbar {
display: flex;
gap: 0.5rem;
}
.gallery {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1rem;
}
display: flexlines children up in a row (or column) and controls how they share space.display: gridplaces children into rows and columns at the same time.
The element itself still behaves like a block on the outside. Only its children change. Both have inline versions too, inline-flex and inline-grid, which sit in a line of text.
Flexbox starts a few lessons from now, and Grid follows. They replace almost every old layout trick, including floats and inline-block rows.
The two-value syntax
The spec now describes display as two parts: the outer type (how the box sits among its siblings) and the inner type (how it lays out its children). You may see this written out:
.card {
display: block flex; /* same as display: flex */
}
.badge {
display: inline flex; /* same as display: inline-flex */
}
The single-keyword forms remain the norm and work everywhere.
A note on display: contents
display: contents makes the element's own box disappear so its children act as children of the grandparent. It can be useful in Grid layouts, but browsers have historically had bugs where it removed the element's meaning for assistive technology, for example on buttons or lists. Avoid it on interactive or semantic elements, and test carefully if you use it.
Summary
- Block boxes start on a new line, fill the width and accept all sizing.
- Inline boxes flow in text, ignore width and height, and ignore vertical margins.
inline-blockflows in text but accepts sizing and spacing.display: noneremoves an element for everyone;visibilityandopacitykeep its space.display: flexanddisplay: gridchange how children are laid out; they are the modern layout tools.