The Display Property

📐 Chapter 6 — The display Property

Every HTML element has a default layout behaviour — some elements stack vertically and stretch to fill the available width; others flow alongside text and shrink to fit their content. The display property is the switch that controls this behaviour, and changing it is one of the most powerful single-property changes you can make in CSS. Understanding block, inline, and inline-block is the foundation of everything that comes after — including Flexbox and Grid.

1 — How display Works

The display property does two things simultaneously: it controls how the element itself is laid out in the page flow (its outer display type), and how its children are arranged inside it (its inner display type). For now, we are focusing on the outer type — block, inline, and inline-block. Flexbox and Grid, which control the inner arrangement of children, are covered in the Intermediate course.

🎨 CSS — The display property
.element { display: block; } /* stacks vertically, full width */ .element { display: inline; } /* flows with text, no width/height */ .element { display: inline-block; } /* flows with text, accepts width/height */ .element { display: none; } /* removed from layout entirely */ .element { display: flex; } /* block-level flex container (Intermediate) */ .element { display: grid; } /* block-level grid container (Intermediate) */

2 — display: block

A block element:

  • Starts on a new line — always breaks away from what came before it.
  • Stretches to fill the full width of its containing element by default.
  • Stacks vertically — each block element sits below the last.
  • Respects all box model properties — width, height, margin, and padding all work as expected.
Live demo — three block elements stack vertically and fill the width
Block A — stretches to fill available width
Block B — starts on a new line automatically
Block C — each block takes up its own row
🎨 CSS — Block element behaviour
.block-box { display: block; width: 300px; /* width works — limits stretching */ height: 80px; /* height works */ padding: 16px; /* padding works on all four sides */ margin: 20px 0; /* margin works on all four sides */ background-color: #1a2e1a; } /* Without a width set, a block fills its container */ .full-width { display: block; /* no width — stretches to 100% of parent */ }

Common block elements

These HTML elements are block by default — you do not need to set display: block on them:

<div>   <p>   <h1>–<h6>   <ul>   <ol>   <li>   <section>   <article>   <header>   <footer>   <nav>   <main>   <aside>   <form>   <blockquote>   <pre>   <hr>   <table>

3 — display: inline

An inline element:

  • Flows with the surrounding text — it does not break onto a new line.
  • Shrinks to fit its content — it takes up only as much space as its content needs.
  • Ignores width and height — you cannot set these properties on an inline element.
  • Respects horizontal padding and margin only — vertical padding and margin are applied visually but do not push surrounding block elements away.
Live demo — inline elements flow within the surrounding text
This is a paragraph of text. The word inline A sits inside the flow. So does inline B, and inline C as well. Notice how they wrap naturally within the line like words, not like separate boxes.
🎨 CSS — Inline element behaviour
span { display: inline; /* default for span — shown here for clarity */ color: #ffd580; /* colour works */ background: #2a1e0a; /* background works */ padding: 2px 6px; /* horizontal padding works as expected */ /* vertical padding shows but doesn't push block siblings */ width: 200px; /* IGNORED — width has no effect on inline */ height: 50px; /* IGNORED — height has no effect on inline */ margin-top: 20px; /* IGNORED — vertical margin doesn't affect flow */ }
The rules about inline elements ignoring width/height are a common source of confusion. If you need to set a width or height on an element that should still flow with text, use inline-block.

Common inline elements

<span>   <a>   <strong>   <em>   <code>   <img>   <button>   <input>   <label>   <abbr>   <cite>   <sup>   <sub>

img, button, and input are special. These elements are technically inline (or inline-block in most browsers) but behave more like block elements in that they do respect width and height. They are called replaced elements — the browser replaces them with external content (an image, a widget) — and they follow slightly different rules.

4 — display: inline-block

inline-block gives you the best of both worlds:

  • Flows with surrounding content like an inline element — sits next to other elements on the same line.
  • Respects width, height, padding, and margin on all sides — just like a block element.

This makes inline-block the go-to for elements that should sit side by side but still need a defined size — buttons, navigation items, image thumbnails, badges.

Live demo — inline-block elements sit side by side and accept width/height
Box A
width: 120px
Box B
width: 120px
Box C
width: 120px
🎨 CSS — inline-block in practice
/* Navigation links side by side with padding */ nav a { display: inline-block; padding: 10px 20px; background: #1a1d27; border-radius: 4px; text-decoration: none; } /* Fixed-size image thumbnails in a row */ .thumbnail { display: inline-block; width: 100px; height: 100px; object-fit: cover; border-radius:4px; margin-right: 8px; } /* Badges / tags */ .badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 0.8rem; font-weight: 600; vertical-align:middle; }

The whitespace gap problem

When you write inline-block elements on separate lines in your HTML, the browser treats the newline character between them as a space — creating a small gap between the elements that you did not add with margin. This is a well-known quirk.

🌐 HTML — The whitespace gap appears between these elements
<!-- These three items will have a small gap between them --> <div class="item">One</div> <div class="item">Two</div> <div class="item">Three</div> <!-- Workaround 1: put closing/opening tags on the same line --> <div class="item">One</div><div class="item">Two</div><div class="item">Three</div>
🎨 CSS — Workaround 2: set font-size to 0 on the parent
.parent { font-size: 0; /* collapses the whitespace text node */ } .parent .item { display: inline-block; font-size: 1rem; /* restore font size on the children */ }
In modern projects, Flexbox has largely replaced inline-block for side-by-side layouts — it has no whitespace gap issue and provides far more control. But inline-block remains useful for elements that genuinely need to flow inline with text.

5 — Side-by-Side Comparison

block
Starts on a new line
Stretches to full width by default
width and height work
All margin and padding work
Cannot sit next to other elements
inline
Flows with surrounding text
Shrinks to content width
width and height ignored
~ Horizontal padding/margin work; vertical padding shows but doesn't push siblings
Sits alongside other content
inline-block
Flows with surrounding content
Shrinks to content (or set width)
width and height work
All margin and padding work
Sits alongside other elements

6 — display: none

display: none removes an element from the page entirely — it takes up no space and is completely invisible. The element still exists in the HTML; it is just not rendered. This is commonly used to show and hide elements with JavaScript.

🎨 CSS — display: none vs visibility: hidden
/* display: none — element removed from layout, no space taken */ .hidden { display: none; } /* visibility: hidden — element invisible but STILL takes up space */ .invisible { visibility: hidden; } /* opacity: 0 — also invisible but still takes space AND is interactive */ .transparent { opacity: 0; } /* Toggling with a class (JavaScript adds/removes .is-open) */ .dropdown { display: none; } .dropdown.is-open { display: block; }
⚠️ display: none is not accessible hiding. Screen readers also skip elements with display: none. If you need to hide something visually but keep it available to assistive technology (e.g. a label for an icon-only button), use the visually-hidden pattern instead — a CSS class that positions the element off-screen without removing it from the accessibility tree.

7 — Changing Default Display Values

One of the most common uses of display is overriding the default. You regularly need to make an inline element behave like a block, or make a block element flow inline.

🎨 CSS — Common display overrides
/* Make links fill their container (e.g. nav links as blocks) */ nav a { display: block; padding: 12px 20px; /* now the whole row is clickable */ } /* Make list items sit side by side (horizontal nav) */ ul.nav li { display: inline-block; } /* Make an image a block to remove the inline baseline gap */ img { display: block; /* eliminates the small gap below inline images */ } /* Make a div sit inline with text */ .tag { display: inline-block; padding: 2px 8px; border-radius: 4px; background: #1e2235; font-size: 0.8em; }

8 — Default display Values

Element(s)Default displayNotes
div, p, h1h6, section, article, header, footer, nav, ul, ol, li block Stack vertically, fill width
span, a, strong, em, code, abbr, cite, sup, sub inline Flow with text, no width/height
img, button, input, select, textarea, label inline-block (or inline) Flow with text but accept width/height — behaviour varies slightly by browser
table table Block-level, but uses table layout internally
td, th table-cell Inside a table only

9 — Looking Ahead: flex and grid

Two more display values — flex and grid — are the foundation of modern CSS layout and are covered in full in Chapters 1–4 of the Intermediate course. Both create a block-level container whose children are laid out according to powerful new rules:

display: flex — one-dimensional layout
Arranges children in a row (or column). Controls alignment, spacing, and order. The most common tool for navigation bars, card rows, and any horizontal layout.
.nav { display: flex; gap: 16px; align-items: center; justify-content: space-between; }
display: grid — two-dimensional layout
Arranges children in rows AND columns simultaneously. Ideal for page layouts, galleries, and any design that needs precise two-axis control.
.page { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: auto 1fr auto; gap: 24px; }
💡 In modern CSS, Flexbox has replaced most uses of inline-block. If you find yourself reaching for inline-block to put elements side by side, consider whether a display: flex on the parent would serve you better — it handles alignment and spacing far more cleanly, with no whitespace gap problem. But inline-block still has its place when you genuinely need elements to flow within text.

10 — Quick Reference

ValueNew line?Full width?Width/Height?Best for
block Yes Yes (default) Yes Structural containers, paragraphs, headings
inline No No — shrinks to content No Text emphasis, links within paragraphs
inline-block No No — shrinks to content Yes Buttons, badges, nav items, image rows
none Hiding elements completely (JS toggling)
flex Yes (container) Yes (container) Yes Rows, columns, alignment — see Intermediate Ch.1–2
grid Yes (container) Yes (container) Yes Two-axis layouts — see Intermediate Ch.3–4

✏️ Exercises

Each exercise asks you to observe or change display behaviour. Open your browser's DevTools alongside each one — inspect the computed display value of elements and watch how the layout changes as you modify it.

Exercise 1
Create a page with three <span> elements (normally inline) and three <div> elements (normally block). First observe them in their default state, then swap their display values: make the spans behave like blocks and the divs behave like inline elements. Give each a different background colour and some padding so the change is clearly visible.
Hint: apply display: block to the span elements and display: inline to the div elements. Use a class to target each group separately.
HTML
<span class="as-block">Span A</span> <span class="as-block">Span B</span> <span class="as-block">Span C</span> <hr> <div class="as-inline">Div X</div> <div class="as-inline">Div Y</div> <div class="as-inline">Div Z</div>
CSS
/* Spans made block */ .as-block { display: block; padding: 10px 16px; margin: 6px 0; background: #1a2e1a; border: 1px solid #7ecfa0; color: #7ecfa0; font-family:system-ui, sans-serif; } /* Divs made inline */ .as-inline { display: inline; padding: 2px 8px; background: #1a1a2e; border: 1px solid #4f8ef7; color: #4f8ef7; font-family:system-ui, sans-serif; }
Exercise 2
Build a horizontal navigation bar using only <ul> and <li> elements — no extra wrapper divs. By default, <li> is a block element and the list stacks vertically. Change the <li> elements to inline-block to make them horizontal. Remove the list bullets, give each item padding, and style the links inside them. The whole item area (not just the link text) should be clickable.
Hint: use list-style: none on the <ul> to remove bullets. Make the <a> inside each <li> display: block so its padding fills the entire cell — this makes the full padded area clickable.
HTML
<ul class="horiz-nav"> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Projects</a></li> <li><a href="#">Contact</a></li> </ul>
CSS
.horiz-nav { list-style: none; padding: 0; margin: 0; background: #12141e; font-size: 0; /* collapse whitespace gap */ } .horiz-nav li { display: inline-block; font-size: 1rem; /* restore after the font-size:0 hack */ } .horiz-nav a { display: block; padding: 14px 20px; color: #a0a4b8; text-decoration: none; font-family: system-ui, sans-serif; font-size: 0.88rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; } .horiz-nav a:hover { color: #ffffff; background: #1e2235; }
Exercise 3
Build a tag/badge system. Create a paragraph of text with several <span class="tag"> elements inside it. Style the tags as inline-block with a rounded background, small padding, and a font smaller than the surrounding text. The tags should sit naturally within the text flow, not break onto their own line. Then, below the paragraph, create a standalone row of the same tags — notice they still flow left-to-right like inline elements.
Hint: display: inline-block with padding: 2px 10px; border-radius: 999px; creates a pill-shaped tag. Use vertical-align: middle to align them nicely with the surrounding text baseline.
CSS
.tag { display: inline-block; padding: 2px 10px; border-radius: 999px; background: #1e2235; border: 1px solid #2a2d3a; color: #7ab8ff; font-family: system-ui, sans-serif; font-size: 0.78em; font-weight: 600; vertical-align: middle; margin: 0 2px; }
Exercise 4
Create a show/hide toggle. Build a panel <div class="panel"> with some content inside it, and a <button> above it. Using a small amount of JavaScript, toggle a class of is-hidden on the panel when the button is clicked. In your CSS, set .is-hidden { display: none; }. The button text should change between "Show panel" and "Hide panel" depending on the state.
Hint: use element.classList.toggle('is-hidden') in a click event listener. For the button text, check panel.classList.contains('is-hidden') after toggling and update btn.textContent.
HTML
<button id="toggle-btn">Hide panel</button> <div class="panel" id="my-panel"> <h3>This is the panel</h3> <p>Click the button to hide or show this content.</p> </div>
CSS
.panel { background: #1a1d27; border: 1px solid #2a2d3a; border-radius:6px; padding: 20px; margin-top: 12px; color: #e2e4ec; font-family: Georgia, serif; } .is-hidden { display: none; }
JavaScript
const btn = document.getElementById('toggle-btn'); const panel = document.getElementById('my-panel'); btn.addEventListener('click', () => { panel.classList.toggle('is-hidden'); btn.textContent = panel.classList.contains('is-hidden') ? 'Show panel' : 'Hide panel'; });

This pattern — toggling a class that sets display: none — is one of the most common JavaScript/CSS patterns in web development. Dropdowns, modals, accordions, and tabs all use variations of it.