Display: block, inline and inline-block

How the display property changes the way an element sits in the page, with a first look at flex and grid.

  • Beginner
  • 6 min read
  • Updated 17 Oct 2026

What you will learn

  • Predict block and inline behaviour
  • Change an element's display type
  • Hide elements correctly with display: none
  • Recognise when to reach for flex or grid

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.

HTML
<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, margin and padding on 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 width and height.
  • 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).

CSS
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:

HTML
<p>
    <a class="button" href="/order">Order now</a>
    <a class="button" href="/menu">See the menu</a>
</p>
CSS
.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.

Behaviourblockinlineinline-block
Starts on a new lineYesNoNo
Default widthFull available widthContent widthContent width
width and height applyYesNoYes
Vertical margin affects layoutYesNoYes

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:

CSS
.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.

CSS
.is-hidden {
    display: none;
}

Compare with visibility: hidden, which hides the element but keeps its space:

TechniqueVisibleTakes spaceAnnounced by screen readers
display: noneNoNoNo
visibility: hiddenNoYesNo
opacity: 0NoYesYes

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:

CSS
.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:

CSS
.toolbar {
    display: flex;
    gap: 0.5rem;
}

.gallery {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1rem;
}
  • display: flex lines children up in a row (or column) and controls how they share space.
  • display: grid places 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:

CSS
.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-block flows in text but accepts sizing and spacing.
  • display: none removes an element for everyone; visibility and opacity keep its space.
  • display: flex and display: grid change how children are laid out; they are the modern layout tools.

Further reading