ESC

Type to search the knowledge base.

Display Block Inline Flex Grid

How display changes layout participation — block vs inline vs inline-block, and when flex/grid formatting contexts take over.

beginner3 min read
  • css
  • display
  • layout

display decides how a box participates in layout and what formatting context it creates for its children. Confusing inline with inline-block, or expecting margins to behave the same on every display type, is the root of many “mystery spacing” bugs.

Docs: MDN display, flow layout.

Outer vs inner (mental model)

Modern display is two-axis: outer (block-level vs inline-level) and inner (flow, flex, grid, …).

.panel {
  display: block; /* outer block-level, inner flow */
}
.chip {
  display: inline-flex; /* outer inline-level, inner flex */
}
.gallery {
  display: grid; /* outer block-level, inner grid */
}

You care about both: “does this break onto its own line?” and “how do my children layout?”

Block vs inline vs inline-block

Value Line breaking Width/height Vertical margin/padding
block Starts on new line; full available width by default Honored Honored
inline Flows with text Width/height largely ignored Horizontal padding/margin apply; vertical is quirky
inline-block Flows with text like a word Honored Honored
span.pill {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  background: var(--brand-soft);
  border-radius: 999px;
}

.full {
  display: block;
  width: 100%;
}

Raw inline is for text-level semantics (<a>, <strong>). When you need a box model on something that still sits in a line, use inline-block or inline-flex.

Flex and grid formatting contexts

.row {
  display: flex; /* children become flex items */
  gap: 0.5rem;
}

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
}

Direct children stop being ordinary block/inline boxes in flow layout and become flex/grid items with different min-size and alignment rules.

.nav {
  display: flex;
}

.nav > a {
  /* flex items — float ignored, vertical-align mostly irrelevant */
}

display: none vs visibility / inert

.hidden {
  display: none; /* not in box tree; no layout, not clickable */
}

.invisible {
  visibility: hidden; /* takes space; not visible */
}

display: none removes accessibility exposure in the usual sense (not rendered). Don’t use it for “visually hidden but SR-readable” — use a proper .sr-only pattern instead.

Common product patterns

/* Button that sizes to content but can still flex-align */
.button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

/* Stretch to full width on mobile */
.button--block {
  display: flex;
  width: 100%;
  justify-content: center;
}

/* Replace table-ish layout */
.stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

Interview out-loud

“display controls outer participation (block-level vs inline-level) and the inner layout mode (flow, flex, grid). Block boxes stack vertically; inline flows with text; inline-block is a hybrid box. Flex and grid create new formatting contexts for children. display: none removes the box entirely unlike visibility: hidden.”

Footguns

  1. Setting width on pure inline elements.
  2. Whitespace gaps between inline-block siblings (use flex/grid instead).
  3. Expecting float to work on flex items.
  4. Toggling display to animate open/close without a plan.
  5. Using inline for multi-line form controls.

Further reading

Related guides