CSS Portal

The difference between display: none & visibility: hidden

If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!
The difference between display: none & visibility: hidden

If you’ve ever needed to hide an element on a page, you’ve probably reached for one of these two CSS properties. At first glance they seem identical – the element disappears. But under the hood, they solve the problem in fundamentally different ways, and choosing the wrong one can cause subtle, frustrating layout bugs.

The key distinction: display: none removes the element entirely from the document flow, as if it never existed. visibility: hidden hides the element visually but preserves its space in the layout.

display: none – gone without a trace

When you apply display: none to an element, the browser completely removes it from the document’s rendering tree. This means the element is not just hidden visually – it no longer participates in layout calculations at all. The space it would have occupied disappears instantly, so surrounding elements shift to fill the gap as though the element were never present. Margins, padding, and dimensions associated with that element are ignored, and any child elements are also excluded from rendering. Because it is effectively taken out of the flow, the page reflows to accommodate the change, which can affect positioning, alignment, and even performance if large sections of the layout are toggled on and off.

.hidden-box {
  display: none; /* element is fully removed from flow */
}

display: none – interactive demo

Box A – always visible
Box B – toggle me
Box C – always visible

Notice how when Box B is hidden, Box C immediately shifts upward to occupy the freed space. Because the hidden element no longer contributes to layout, the browser recalculates positions and closes the gap as if Box B were never there. There’s no reserved placeholder, no invisible footprint left behind – just a seamless reflow of the surrounding content. This behaviour makes display: none especially useful for conditionally rendered interface components such as modals, dropdown menus, tab panels, or expandable sections, where you want elements to appear and disappear without leaving awkward spacing or disrupting the overall structure of the page.

Note: Elements with display: none are also removed from the accessibility tree and cannot be focused by keyboard navigation.
If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!

visibility: hidden – the invisible ghost

visibility: hidden hides the element’s visual output while keeping the element itself in the layout. Unlike display: none, the browser still calculates its dimensions, margins, and position, so the space it would normally occupy remains reserved. The element becomes invisible rather than removed, almost like a transparent placeholder sitting in the same spot. Because it continues to participate in the document flow, surrounding elements do not shift to fill the gap, which can be useful when you need to temporarily conceal content without affecting alignment or causing layout changes.

.ghost-box {
  visibility: hidden; /* invisible, but space is preserved */
}

/* Children can override it! */
.ghost-box .child {
  visibility: visible; /* this child will show through */
}

visibility: hidden – ghost demo

Box A – always visible
Box B – toggle me
Box C – always visible

See it? Box B disappears from view, yet the space it occupied is still preserved – Box C remains anchored in the same position. Because the element is only made invisible rather than removed, the browser keeps its dimensions in the layout, preventing any reflow or sudden movement of surrounding content. This results in a stable, non-jumping interface, which can be particularly helpful when toggling temporary states, preparing content for animations, or hiding elements that are expected to reappear quickly without disrupting the user’s sense of spatial continuity.

Bonus trick: Unlike display: none, you can override visibility: hidden on child elements by setting visibility: visible on them. Child elements can “show through” a hidden parent.

Side-by-side comparison

Here’s a quick reference for the key differences:

Property display: none visibility: hidden
Preserves layout space ✗ No ✓ Yes
Visible on screen ✗ No ✗ No
Accessible to screen readers ✗ No ✗ No (usually)
Receives pointer events ✗ No ✗ No
Children can override ✗ No ✓ Yes
Animatable with CSS transitions ✗ Not directly ✓ Yes
Triggers layout reflow ✓ Yes (on toggle) ✗ No
Common use case Modals, tabs, conditional UI Stable layouts, fade-in animations

Which one should you use?

Use display: none when you want the element to genuinely not take up space – conditional rendering, toggleable panels, menu items, and anything where reflowing the layout is acceptable or desired.

Use visibility: hidden when you need the space to be held in place – for example, when you’re fading an element in and out and don’t want the surrounding content to jump around. It’s also handy when building skeleton loaders or placeholder layouts.

For smooth fade animations, a common pattern combines both:

.fade-element {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.3s ease, visibility 0.3s;
}

.fade-element.hidden {
  visibility: hidden;
  opacity: 0;
  /* opacity animates smoothly; visibility snaps at the end */
}

This lets the opacity transition animate, while visibility: hidden ensures the element becomes fully non-interactive at the end of the transition (unlike opacity: 0 alone, which is invisible but still clickable).

Dig deeper

Now that you understand the difference, it’s worth exploring the full picture. The display property goes far beyond none – it’s the foundation of Flexbox and Grid. And the visibility property has a third value, collapse, which behaves specially inside tables and subgrids. If you’re reaching for visibility: hidden just to stop clicks, you might also want pointer-events. And if smooth fade-outs are your goal, opacity paired with visibility is the go-to pattern.

If this site has been useful, we’d love your support! Consider buying us a coffee to keep things going strong!