If there’s one CSS property that quietly controls everything about how your page is built, it’s display. Every single element on a web page has a display value, whether you set one or not. It’s the property that decides whether an element stacks on its own line, sits inline with text, disappears entirely, or turns into a powerful layout container.
You’ve already met some of this in passing — when you wrote display: flex to lay out a navbar, that was the display property doing its job. Now let’s slow down and look at the whole picture, because once you really understand display, a huge amount of confusing CSS behavior suddenly makes sense.
What the display property actually does
Every element renders according to a box type, and display sets that box type. It answers two questions at once: how does this element flow relative to its neighbors (does it take a full line, or sit inline?), and what kind of layout does it create for its own children?
The default value depends on the element. A <div>, <p>, or <section> starts life as block. A <span>, <a>, or <strong> starts as inline. You don’t have to set anything for these defaults to apply — the browser already has them baked in. The display property is how you override that default when the default isn’t what you want.
.box {
display: block;
}
That single line can completely change how an element sits on the page. Let’s go through each value you’ll actually use.
block: takes the whole line
A block element starts on a new line and stretches to fill the full width available to it, pushing whatever comes after it down to the next line. Think of paragraphs, headings, and <div> containers — they stack vertically, one on top of the next.
.card {
display: block;
width: 300px;
height: 100px;
background: #e0f7ff;
}
Because block elements respect width and height, you can size them freely. They also honor all four margins and paddings. This is the workhorse box for building structure: containers, sections, cards, and rows.
Block elements fill the width even when content is small
A block element grabs the full available width by default, even if its content is a single short word. That’s why two <div>s stack on top of each other instead of sitting side by side — each one claims the whole line. If you want them next to each other, you’ll need a different display value (or a flex/grid parent), which is exactly what the rest of this article covers.
inline: flows with the text
An inline element is the opposite. It doesn’t break onto a new line — it sits right in the flow of text, only as wide as its content, letting other inline elements line up beside it. Links (<a>), <span>, <strong>, and <em> are all inline by default, which is exactly why you can drop a link into the middle of a sentence without breaking the line.
.highlight {
display: inline;
background: #fff3b0;
}
Here’s the catch that trips people up: width and height are ignored on inline elements. You can’t give a <span> a fixed height by setting height: 50px — it’ll have no effect. The same goes for top and bottom margins; they’re ignored too. Inline elements are meant to wrap around text, so the browser only lets you control their horizontal spacing, not their vertical size.
width and height do nothing on inline elements
This is one of the most common beginner head-scratchers. You set width and height on a <span> or an <a>, refresh the page, and… nothing changes. That’s not a bug — inline elements simply don’t accept those properties. If you need to size the element, switch it to inline-block or block. Keep this rule in your back pocket; it’ll save you a lot of confused debugging.
inline-block: the best of both
What if you want an element to sit inline (next to other things, flowing with the text) but also accept a width and height? That’s exactly what inline-block is for. It flows horizontally like an inline element, but behaves like a block on the inside — so width, height, and all margins and paddings work normally.
.tag {
display: inline-block;
width: 80px;
height: 30px;
padding: 4px 8px;
background: #00b8e6;
color: #fff;
}
This is perfect for things like tags, badges, or buttons that should line up in a row but still have a fixed size and proper padding. Before flexbox came along, inline-block was the go-to trick for putting boxes side by side. It still has its place today, especially for small inline UI pieces.
| Value | New line? | Respects width/height? | Sits beside others? |
|---|---|---|---|
block |
Yes | Yes | No |
inline |
No | No | Yes |
inline-block |
No | Yes | Yes |
That table sums up the three traditional flow values. Once those click, the modern layout values are easy to add on top.
none: completely removed
Setting display: none removes an element from the page entirely. It’s not just hidden — it takes up zero space, as if it were never in the HTML at all. Nothing flows around it, nothing reserves room for it.
.modal {
display: none; /* hidden — takes no space */
}
.modal.open {
display: block; /* shown when the "open" class is added */
}
This is the classic pattern for showing and hiding things like modals, dropdowns, and menus: toggle between display: none and display: block (often by adding or removing a class with JavaScript). The element vanishes and reappears cleanly.
display: none vs visibility: hidden
These two look similar but behave very differently. display: none removes the element completely — it takes up no space. visibility: hidden only makes the element invisible, but it still occupies its space in the layout, leaving a gap where it used to be. Reach for display: none when you want the element gone, and visibility: hidden on the rare occasion you want it invisible but still holding its place.
flex and grid: layout containers
The two values you’ll lean on most for real layouts are flex and grid. Setting one of these on an element doesn’t just change how that element flows — it turns the element into a powerful container that controls how its children are arranged.
.row {
display: flex; /* children lay out in a row or column */
}
.gallery {
display: grid; /* children lay out in a 2D grid */
}
display: flex is your tool for one-dimensional layout — a single row or a single column of items, with easy spacing and alignment. display: grid handles two-dimensional layout — rows and columns at the same time, like a real page structure. These two are the backbone of modern CSS layout, and each deserves a deep dive of its own.
If you want the full story on those, the dedicated guides on CSS Flexbox and CSS Grid walk through every property. For now, the key takeaway is that flex and grid are display values — the layout magic starts the moment you set one on a container.
How display fits with the box model
It helps to remember how display connects to everything else you’ve learned. Whether width, height, margins, and padding apply at all depends on the display value — block-level boxes use the full box model, inline boxes only honor part of it. If the terms width, padding, and margin feel shaky, the CSS Box Model guide is worth a quick revisit, because display and the box model work hand in hand.
The mental model is: display decides what kind of box an element is, and the box model decides how that box is measured. Together they explain almost everything about why an element sits where it sits and sizes the way it sizes.
Picking the right value
In day-to-day work you won’t agonize over this — a few rules of thumb cover most cases:
- Use the defaults most of the time. A
<div>is alreadyblock; a<span>is alreadyinline. Don’t change them unless you need to. - Reach for
inline-blockwhen you want inline placement plus a fixed width or height — tags, badges, small buttons in a row. - Use
flexorgridon a container whenever you’re arranging multiple children — this is the modern way to build layouts, and you’ll use it constantly. - Use
noneto show and hide elements, usually toggled with a class via JavaScript.
That’s genuinely 95% of what you’ll ever need. The exotic display values exist, but you can pick them up later when a specific problem calls for them.
Wrapping up
The display property is the foundation everything else in layout is built on. Get comfortable with it and a lot of CSS confusion melts away:
- Every element has a
displayvalue —blockandinlineare the most common defaults. blocktakes a full line and respects width/height;inlineflows with text and ignores width/height.inline-blockcombines both: inline placement with a real width and height.noneremoves an element completely (zero space), the standard way to show/hide things.flexandgridturn an element into a layout container for its children — the heart of modern CSS layout.
Once display clicks, the natural next questions are about positioning — how to nudge an element out of the normal flow, layer things on top of each other, or pin something to the corner of the screen. That’s where properties like position and z-index come in, and they’re the perfect next step from here.