The CSS Display Property

▶ Try It Yourself

Every HTML element has a default display type that determines how it participates in the page flow — whether it starts a new line, sits inline with text, or is removed from the flow entirely. The display property is the single most important layout property in CSS, and understanding its values is the prerequisite for mastering Flexbox, Grid, and positioning. In this lesson you will learn every major display value and exactly when to use each one.

Core Display Values

Value Flow Behaviour Width Behaviour Default Elements
block Starts on a new line; takes full available width Respects width/height div, p, h1-h6, section
inline Flows with text; no line break before/after Ignores width/height; sized by content span, a, strong, em
inline-block Flows with text like inline Respects width, height, padding, margin None by default — set explicitly
none Removed from layout and accessibility tree Takes no space at all Used to toggle visibility
flex Block-level; creates flex formatting context for children Respects width/height None by default — set explicitly
grid Block-level; creates grid formatting context for children Respects width/height None by default — set explicitly
inline-flex Inline-level flex container — sits in text flow Sized by content (like inline) None by default — badges, tags

display: none vs visibility: hidden

Property Space in Layout Accessible to Screen Readers Use Case
display: none No — element is completely removed No — hidden from accessibility tree Toggle elements on/off (menus, modals)
visibility: hidden Yes — space is preserved No — hidden from accessibility tree Animate out while keeping layout stable
opacity: 0 Yes — space is preserved Yes — still accessible and interactive Fade animations; still receives pointer events

block vs inline-block Key Differences

Feature block inline-block
New line Yes — always starts on its own line No — flows inline with surrounding content
width / height Fully respected Fully respected
vertical margin Fully respected Fully respected
Use case Sections, containers, paragraphs Buttons, badges, nav items in text
Note: display: none removes the element from both visual layout and the accessibility tree. If you need content to be hidden visually but remain accessible to screen readers (e.g. a skip-navigation link), use the visually-hidden CSS technique instead: position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0);
Tip: Use display: inline-flex for small component containers like badges, tags, and chip elements that need to flow inline with text but require internal flex alignment of an icon + label. It behaves like an inline element from the outside and like a flex container on the inside.
Warning: Setting display: block on an anchor tag (<a>) changes its inline behaviour — the entire block becomes clickable but it will start on a new line. Use display: inline-block if you want it to remain inline but respect padding and size. Use display: block inside navigation lists where the full row should be clickable.

Basic Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>CSS Display Values</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; padding: 32px; background: #f8fafc; line-height: 1.6; }

    /* block — new line, full width */
    .demo-block {
      display: block;
      background: #ede9fe;
      border-left: 4px solid #7c3aed;
      padding: 12px 16px;
      margin-bottom: 12px;
      border-radius: 0 8px 8px 0;
    }

    /* inline — flows in text, ignores width/height */
    .demo-inline {
      display: inline;
      background: #fef9c3;
      padding: 2px 6px;
      border-radius: 4px;
      font-weight: 600;
    }

    /* inline-block — flows in text but respects sizing */
    .demo-inline-block {
      display: inline-block;
      background: #d1fae5;
      border: 1px solid #6ee7b7;
      padding: 8px 16px;
      border-radius: 6px;
      font-weight: 600;
      margin: 4px;
      /* width and height are respected here unlike plain inline */
      min-width: 100px;
      text-align: center;
    }

    /* Toggling display: none */
    .hidden-demo { display: none; } /* takes NO space */
    .invisible-demo { visibility: hidden; } /* space preserved */

    /* inline-flex badge example */
    .badge {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      background: #4f46e5;
      color: white;
      padding: 3px 10px;
      border-radius: 9999px;
      font-size: 0.75rem;
      font-weight: 700;
    }

    /* Block link — full-width clickable row */
    .nav-link {
      display: block;
      padding: 12px 20px;
      background: white;
      border: 1px solid #e2e8f0;
      border-radius: 8px;
      text-decoration: none;
      color: #1e293b;
      margin-bottom: 8px;
      font-weight: 500;
      transition: background 0.15s, border-color 0.15s;
    }
    .nav-link:hover { background: #ede9fe; border-color: #c4b5fd; }
  </style>
</head>
<body>

  <div class="demo-block">display: block — starts on its own line, full width</div>
  <div class="demo-block">Second block — also on its own line</div>

  <p>
    Normal paragraph text with
    <span class="demo-inline">inline span</span>
    that flows naturally — and another
    <span class="demo-inline">inline badge</span>
    right here in the text.
  </p>

  <p>
    Inline-block elements sit in text flow but respect sizing:
    <span class="demo-inline-block">Button A</span>
    <span class="demo-inline-block">Button B</span>
    <span class="demo-inline-block">Btn C</span>
    — back to regular text.
  </p>

  <p>display: none removes the box: [<span class="hidden-demo">HIDDEN</span>] — no gap there.</p>
  <p>visibility: hidden preserves space: [<span class="invisible-demo">INVISIBLE</span>] — gap remains.</p>

  <p>
    inline-flex badge in text:
    <span class="badge">✓ Verified</span>
    — flows with surrounding content.
  </p>

  <a href="#" class="nav-link">Block-level link — entire row is clickable</a>
  <a href="#" class="nav-link">Second block-level link</a>

</body>
</html>

How It Works

Step 1 — Block Elements Stack Vertically

Each .demo-block div creates its own line in the flow. Even with text content shorter than the viewport, a block element extends to the full container width. Siblings stack below it regardless of available horizontal space.

Step 2 — Inline Elements Run in Text Flow

The two .demo-inline spans sit between words without breaking the line. They cannot have a meaningful width, height, or vertical margin — those properties are simply ignored for inline elements.

Step 3 — Inline-Block Bridges Both Worlds

The three .demo-inline-block spans sit side by side on the same line (inline behaviour) but each has a min-width that is honoured (block behaviour). This makes them ideal for button groups that must live within a paragraph or heading.

Step 4 — display: none Collapses the Box Entirely

The hidden span produces no rendered box whatsoever — the bracketed text around it appears with no gap. In contrast, the visibility:hidden span leaves a blank space exactly equal to its rendered size.

Step 5 — inline-flex Enables Internal Alignment Within Text Flow

The badge is inline-flex so it aligns the checkmark and text vertically via align-items: center — not possible with plain inline. From the outside it flows naturally in the sentence, from the inside it is a flex container.

/* sidebar-nav.css */
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; margin: 0; }

.sidebar {
  width: 260px;
  background: #1e293b;
  min-height: 100vh;
  padding: 24px 0;
}

.nav-section-label {
  display: block;           /* block so it fills full width */
  padding: 6px 20px;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #64748b;
  margin-bottom: 4px;
}

.nav-item {
  display: flex;            /* flex container for icon + text */
  align-items: center;
  gap: 10px;
  padding: 10px 20px;
  color: #94a3b8;
  text-decoration: none;
  font-size: 0.875rem;
  border-radius: 0;
  transition: background 0.15s, color 0.15s;
}
.nav-item:hover { background: #334155; color: #f1f5f9; }
.nav-item.active { background: #312e81; color: #a5b4fc; font-weight: 600; }

.nav-icon {
  display: inline-flex;     /* inline-flex for icon centering */
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  font-size: 1rem;
}

.nav-badge {
  display: inline-flex;
  align-items: center;
  margin-left: auto;
  background: #4f46e5;
  color: white;
  font-size: 0.65rem;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 9999px;
  min-width: 20px;
  justify-content: center;
}

/* Divider */
.nav-divider {
  display: block;
  height: 1px;
  background: #334155;
  margin: 12px 20px;
}

Common Mistakes

Mistake 1 — Setting width/height on inline elements

❌ Wrong — width and height are ignored on inline elements:

span { display: inline; width: 200px; height: 40px; } /* has no effect */

✅ Correct — switch to inline-block or block to apply sizing:

span { display: inline-block; width: 200px; height: 40px; }

Mistake 2 — Using display: none for accessible content

❌ Wrong — screen readers cannot reach this content:

.skip-link { display: none; } /* inaccessible to keyboard/screen reader */

✅ Correct — use the visually-hidden technique to hide only visually:

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

Mistake 3 — Unexpected gaps between inline-block elements

❌ Wrong — whitespace in HTML creates a small gap between inline-block items:

<span class="btn">A</span>
<span class="btn">B</span> <!-- gap appears between A and B -->

✅ Correct — use flexbox on the parent to eliminate whitespace gaps entirely:

.btn-group { display: flex; gap: 8px; }
.btn-group .btn { /* no display: inline-block needed */ }

▶ Try It Yourself

Quick Reference

Value New Line? Width/Height? Common Use
block Yes Yes Containers, headings, paragraphs
inline No No Text styling: span, a, strong
inline-block No Yes Buttons within text, nav pills
none Toggle elements; removes from layout
flex Yes (outer) Yes Row/column layout of children
inline-flex No Content-sized Badges, chips, icon+label in text
grid Yes (outer) Yes Two-dimensional child layout

🧠 Test Yourself

You want a badge element to flow inline within a sentence AND have its icon and label vertically centered. Which display value is best?





▶ Try It Yourself