The Display Property
Control how elements are laid out — block, inline, inline-block, flex, grid, none, and more.
1. Introduction
Every HTML element has a default display value — and this controls how it behaves in the page flow. A <div> takes up the full line width. A <span> sits inline with text. An <img> acts like an inline element.
The display property is one of the most important in CSS because it determines:
- Whether the element starts on a new line or flows with text
- Whether you can set a width and height on it
- Whether its children are arranged using Flexbox or Grid
- Whether the element renders at all
In this lesson we cover all the key display values you need to know.
2. Theory
display: block
Block elements:
- Start on a new line
- Take up the full width of their parent
- Respect width, height, margin, padding
Default block elements: div, p, h1-h6, ul, ol, li, header, main, section, article, footer, form
div { display: block; } /* already default — no need to set this */
display: inline
Inline elements:
- Flow within text — no new line
- Width and height are ignored — sized to content
- Horizontal padding and margin work; vertical is unpredictable
Default inline elements: span, a, strong, em, img, button, input, label
span { display: inline; } /* already default */
/* You can make a block inline: */
p { display: inline; } /* paragraphs flow inline — rarely useful */
display: inline-block
The best of both worlds:
- Flows inline (no new line) like inline elements
- Accepts width, height, vertical margin/padding like block elements
.badge {
display: inline-block;
padding: 4px 12px;
background: #dbeafe;
color: #1d4ed8;
border-radius: 999px; /* pill shape */
font-size: 0.75rem;
font-weight: 600;
}
display: none
Completely removes the element from the page — it takes up no space and is invisible. Different from visibility: hidden which hides but preserves space.
.modal { display: none; } /* hidden — no space taken */
.modal.is-open { display: block; } /* show when class added by JS */
/* vs */
.tooltip { visibility: hidden; } /* invisible but still takes up space */
.tooltip:hover { visibility: visible; }
display: flex
Makes the element a flex container. Its children (flex items) are arranged in a row or column using the Flexbox layout model. Covered fully in Module 05.
.nav {
display: flex;
gap: 16px;
align-items: center;
}
display: grid
Makes the element a grid container. Its children are placed on a two-dimensional grid. Covered fully in Module 06.
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
display: inline-flex and inline-grid
Like flex/grid but the container itself behaves as an inline element (sits in text flow).
.tag {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
}
display: table
Makes an element behave like a table. Mostly replaced by Flexbox and Grid today, but occasionally used for centering tricks.
visibility: hidden vs display: none
| Property | Visible? | Takes up space? | Accessible to screen readers? |
|---|---|---|---|
display: none | No | No | No |
visibility: hidden | No | Yes | No |
opacity: 0 | No | Yes | Yes (still clickable!) |
3. Real World Example
The display property is used constantly in real code:
display: flex— navigation bar, button groups, card headersdisplay: grid— photo gallery, feature grid, dashboard layoutdisplay: none— mobile menu (hidden until hamburger clicked), modal (hidden until triggered), tooltipsdisplay: inline-block— pill badges, tags, inline buttonsdisplay: blockon<a>— makes the entire link card clickable area
4. Code Example
/* Navigation: block by default, changed to flex */
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
height: 64px;
background: #1e293b;
}
/* Nav links: normally inline, stay inline */
.nav-link {
color: white;
text-decoration: none;
padding: 8px 12px; /* needs inline-block for padding to work perfectly */
display: inline-block;
}
/* Badges: inline-block for sizing + inline flow */
.badge {
display: inline-block;
padding: 2px 10px;
background: #dbeafe;
color: #1e40af;
border-radius: 999px;
font-size: 0.75rem;
font-weight: 600;
vertical-align: middle;
}
/* Modal: hidden by default */
.modal-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.6);
place-items: center; /* needs display: grid or flex */
}
.modal-overlay.is-open {
display: grid; /* shows and uses grid for centering */
}
/* Mobile nav hidden */
.mobile-nav {
display: none;
}
@media (max-width: 768px) {
.desktop-nav { display: none; }
.mobile-nav { display: block; }
}
/* Image — make it block to remove baseline gap */
img {
display: block;
max-width: 100%;
}
5. Code Breakdown
display: flexon.navbar- Changes the navbar to a flex container, allowing
align-items: center(vertical centering) andjustify-content: space-between(pushes logo left, links right). This is impossible to do cleanly with block/inline. display: inline-blockon.nav-link- Links are inline by default.
inline-blocklets them have consistent padding and a clickable area while still flowing horizontally in the flex container. vertical-align: middleon.badge- When inline/inline-block elements are mixed with text, the default vertical alignment is the text baseline.
middlecentres the badge relative to the surrounding text line height. display: gridon.modal-overlay.is-open- When the modal is shown, the overlay needs to centre its content.
display: grid; place-items: center;is the most concise way to perfectly centre an element both vertically and horizontally. display: blockonimg- Images are inline by default, which causes a small gap at the bottom (the text baseline gap). Making them
display: blockremoves this gap — a very common CSS reset.
6. Common Mistakes
-
Setting width/height on inline elements and wondering why it does not work.
<span>and<a>are inline by default. They ignore width and height. Change toinline-blockorblock. -
Confusing
display: noneandvisibility: hidden.noneremoves the element from flow entirely (no space).hiddenmakes it invisible but preserves its space. Usenonefor toggling menus/modals. -
Not knowing that
opacity: 0elements are still clickable. An element withopacity: 0is invisible but still receives click events — can cause confusing bugs. Usepointer-events: nonealongside it if needed. - Forgetting that inline elements cannot have meaningful vertical margin. Vertical margins on inline elements are unpredictable. Convert to block or inline-block for spacing control.
7. Best Practices
- Use
display: flexfor one-dimensional layouts (rows or columns) — navigation bars, button groups, card headers. - Use
display: gridfor two-dimensional layouts — galleries, dashboards, form layouts. - Use
display: nonefor toggling visibility — it removes the element completely from layout and accessibility tree. - Set
display: blockon images in most contexts to prevent the baseline gap. - Avoid
display: table— Flexbox and Grid have replaced table layout.
8. Practice Exercise
- Create an
<a>tag with justdisplay: inline(default). Notice you cannot control its height withheight: 40px. Switch toinline-blockand confirm height now works. - Create a modal: a div overlay (
display: none) with a centred content box inside. Add a button that adds classis-open. Style.modal.is-open { display: grid; place-items: center; }. - Create three
<span>elements styled as badges (pill shape, coloured background). Useinline-block. - Create a simple navbar using
display: flexwith a logo on the left and 4 links on the right.
9. Assignment
Build a page that demonstrates all the key display values:
- A navbar using
display: flex - A hero section with centred content using
display: grid; place-items: center; - A tag/badge system using
display: inline-block - A "show/hide" button that toggles a
display: nonepanel (use JavaScript or just show both states with CSS classes) - A three-column feature section using
display: grid
10. Interview Questions
Q1: What is the difference between block, inline, and inline-block?
Answer: Block elements start on a new line and fill the full parent width — you can set width, height, and all margins. Inline elements flow within text, ignore width/height, and vertical margin is unreliable. Inline-block sits inline but accepts all box model properties — it is a hybrid.
Q2: What is the difference between display: none and visibility: hidden?
Answer: display: none completely removes the element from the page — it takes up no space and is not rendered. visibility: hidden makes the element invisible but it still occupies its space in the layout, leaving a blank gap.
Q3: How do you horizontally centre an inline element?
Answer: Add text-align: center to the parent element. This works for inline and inline-block children. For block elements, use margin: 0 auto with an explicit width.
Q4: Why might you add display: block to an image?
Answer: Images are inline by default, which causes a small gap at the bottom due to text baseline alignment. Making them display: block removes this unwanted gap — useful inside containers where you want no spacing below the image.
Q5: What does display: flex do?
Answer: It turns the element into a flex container, enabling the Flexbox layout model for its direct children. Children become flex items and can be arranged, aligned, and distributed using properties like flex-direction, justify-content, and align-items.
11. Additional Resources
- MDN Web Docs — display property (search "MDN CSS display")
- CSS-Tricks — A Complete Guide to Flexbox (search "css-tricks flexbox guide")
- MDN — Block and inline layout (search "MDN block inline layout")
- web.dev — Learn CSS Display (search "web.dev learn css display")