Display & Visibility
Why does a <div> start on a new line but a <span> sits inside the sentence? Why does width work on one and not the other? The answer is the display property. It decides what kind of box an element makes and how its children are laid out, so it is the switch behind every layout technique in CSS.
In this lesson you will learn block, inline and inline-block boxes, how display turns on Flexbox and Grid, and the different ways to hide an element, including one that keeps content available to screen readers.
Block and inline
Every element has a default display value from the browser's style sheet. Most elements are either block or inline. (The HTML side of this is in Block & Inline Elements.)
Block boxes, such as <div>, <p>, <h1>, <section> and <ul>:
- start on a new line and stretch to fill the width of their parent;
- respect
width,height, and all margins and padding.
Inline boxes, such as <span>, <a>, <strong> and <em>:
- sit inside a line of text and are only as wide as their content;
- ignore
widthandheight; - take horizontal margins and padding, but vertical margins do nothing, and vertical padding overlaps the lines above and below instead of pushing them away.
Inline-block is a mix: the box flows in the line like inline, but respects width, height and vertical spacing like block. It suits things like small buttons or badges inside a sentence.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>block, inline, inline-block</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; line-height: 1.6; }
span { background: #ffe8cc; border: 1px solid #e0a100; padding: 0.5rem; width: 8rem; margin: 1rem; }
.inline { display: inline; }
.inline-block { display: inline-block; }
.block { display: block; }
</style>
</head>
<body>
<p>Inline: the bus to <span class="inline">Rohtak</span> leaves at nine. Notice the padding overlapping the lines and the width being ignored.</p>
<p>Inline-block: the bus to <span class="inline-block">Rohtak</span> leaves at nine. The width, margin and padding all work, and the line makes room.</p>
<p>Block: the bus to <span class="block">Rohtak</span> leaves at nine. The span now sits on its own line.</p>
</body>
</html>Same element, same styles, three different display values, three different results.
display turns on layout modes
display actually controls two things: how the box behaves outside (block or inline) and how it lays out its children inside. The most important inside values are:
| Value | Outside | Children are laid out with |
|---|---|---|
block | block | normal flow (text and stacked blocks) |
flex | block | Flexbox |
grid | block | Grid |
inline-flex | inline | Flexbox |
inline-grid | inline | Grid |
flow-root | block | normal flow, in a self-contained box |
Modern CSS also lets you write the two parts separately, which makes the meaning clearer. display: inline flex is the same as inline-flex, and display: block flex is the same as flex. The two-value syntax is supported in current versions of all major browsers, but the one-word forms are still the most common in real code.
.toolbar { display: flex; } /* a block-level flex container */
.chip { display: inline-flex; } /* flows in text, lays out its icon and label with flex */
.gallery { display: grid; }flow-root
display: flow-root creates a block that keeps everything inside it contained. Its children's margins can no longer escape through its top or bottom (see margin collapsing in The Box Model), and it fully wraps any floated children. You may see older "clearfix" hacks used for this in old code; flow-root replaces them.
Hiding elements
There are several ways to hide something, and they behave very differently:
| Method | Takes up space? | Can be clicked or focused? | Read by screen readers? |
|---|---|---|---|
display: none | No | No | No |
visibility: hidden | Yes, an empty gap stays | No | No |
opacity: 0 | Yes | Yes | Yes |
| visually hidden class | No | Yes, if focusable | Yes |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hiding elements</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; }
.row { display: flex; gap: 0.5rem; margin-block: 0.75rem; }
.row div { padding: 1rem; background: #d8e6f8; border-radius: 6px; }
.none { display: none; }
.hidden { visibility: hidden; }
.clear { opacity: 0; }
</style>
</head>
<body>
<div class="row"><div>Aarav</div><div class="none">Priya</div><div>Kabir</div></div>
<div class="row"><div>Aarav</div><div class="hidden">Priya</div><div>Kabir</div></div>
<div class="row"><div>Aarav</div><div class="clear">Priya</div><div>Kabir</div></div>
</body>
</html>In the first row, Priya's box is gone and Kabir moves up next to Aarav. In the second and third rows a gap remains where she was. The difference between the last two is invisible here, but important: an element with opacity: 0 is still there for clicks, keyboard focus and screen readers. Use opacity for fade effects in transitions, not to hide content.
The HTML hidden attribute works like display: none, because the browser's default style sheet hides it. Watch out: if your CSS gives that element any display value, for example .menu { display: flex; }, your rule wins and the "hidden" element appears. Many projects add [hidden] { display: none !important; } to protect it.
Hiding visually but keeping it for screen readers
Sometimes text should be available to screen reader users but not shown, such as a label "Search" on an icon-only button. display: none would hide it from everyone. This well-known pattern hides it only visually:
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}The text is shrunk to a single clipped pixel and taken out of the flow, but it stays in the page for assistive technology. See HTML Accessibility for when to use it.
Common mistakes
- Setting
widthon an inline element. It is ignored. Useinline-block, or make the parent a flex container. - Vertical margin on links. Inline elements ignore top and bottom margins. Change
displayif you need them. - Hiding with
opacity: 0. The element can still be clicked and focused. Usedisplay: noneor thehiddenattribute. - Overriding
hiddenby accident. Adisplayrule on an element beats the browser's[hidden]style. display: noneon content meant for screen readers. Use the visually hidden class instead.
Key points
- Block boxes start on a new line and fill the width; inline boxes flow in text and ignore width and height.
inline-blockflows in text but respects width, height and vertical spacing.display: flexanddisplay: gridturn an element into a layout container for its children.display: flow-rootcontains its children's margins and floats.display: noneremoves an element completely;visibility: hiddenkeeps its space;opacity: 0keeps it interactive.- A visually hidden class hides content from the screen while keeping it for screen readers.
Exercise
Make a short sentence about a Jaipur bookshop containing three links styled as small "tag" buttons that sit inside the sentence, have a fixed width of 7rem, padding and rounded corners. Then add an icon-only "Search" button (use the character ⌕) with the word "Search" in a visually hidden span, so screen reader users still hear it.
Show solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bookshop tags</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; line-height: 2; }
.tag {
display: inline-block;
width: 7rem;
text-align: center;
padding: 0.2rem 0.5rem;
border-radius: 999px;
background: #e8eef7;
text-decoration: none;
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
</style>
</head>
<body>
<p>Browse <a class="tag" href="#">Fiction</a>, <a class="tag" href="#">Exam guides</a> or <a class="tag" href="#">Hindi poetry</a> at Pink City Books.</p>
<button type="button">⌕ <span class="visually-hidden">Search</span></button>
</body>
</html>inline-block lets the links keep their place in the sentence while accepting a width, and the hidden span gives the icon button an accessible name.
Quick Quiz
1. Which display value lets an element sit inside a line of text but still accept a width and height?
Inline-block boxes flow with the text but size themselves like block boxes.
2. What is the difference between display: none and visibility: hidden?
Both hide the element, but only visibility: hidden keeps its place in the layout.
3. Why is opacity: 0 a poor way to hide a menu?
Opacity only changes how the element looks; it stays fully interactive.
4. What does display: inline-flex create?
The outside behaves like inline, and the children are laid out with flex.
Learn CSS with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
