Back to CSS
CSS
easy
mid

What is the difference between display none and visibility hidden in CSS?

display:none removes the element entirely — no box, no space taken, not in layout, not announced to screen readers, can't be focused. visibility:hidden hides it visually but it STILL occupies its space in layout and affects siblings. opacity:0 is a third option (visible to a11y/events). Toggling display triggers reflow.

4 min read·~5 min to think through

Both hide an element, but they differ in whether the element still occupies space and participates in the page.

display: none

The element is removed from the render tree entirely, as if it doesn't exist:

  • Takes up no space — the layout closes up around it; siblings move in.
  • Not in the layout at all.
  • Not announced to screen readers, not focusable, doesn't receive events.
  • Its children are also gone from rendering.
  • Toggling it on/off triggers a reflow (layout recalculation).

visibility: hidden

The element is invisible but still there:

  • Still occupies its space — the layout reserves its box; siblings stay put. You get an empty gap.
  • Still in the layout — just not painted.
  • Not focusable, doesn't receive mouse events.
  • By default also hidden from screen readers (though a child can override with visibility: visible).
  • Toggling it triggers a repaint, not a reflow — cheaper.

opacity: 0 — the third option

Worth mentioning: opacity: 0 makes the element fully transparent but it still occupies space AND is still interactive — it can be clicked, focused, and is in the accessibility tree. It's also animatable (and composite-only — cheap). visibility is not smoothly animatable; display definitely isn't.

Quick comparison

display:nonevisibility:hiddenopacity:0
Takes up space❌ no✅ yes✅ yes
In layout
Clickable / focusable
Screen readerhiddenhidden (overridable)announced
Toggle costreflowrepaintcomposite (cheapest)
Animatable❌ (binary)

Which to use

  • display: none — when the element should be completely gone (conditional content, responsive hide). Most common.
  • visibility: hidden — when you want to hide it but preserve the layout space (avoid content jumping) — e.g. a placeholder slot.
  • opacity: 0 — for fade animations, or when you need the element still interactive/measurable.

⚠️ For truly hiding from everyone including assistive tech, display:none or visibility:hidden are correct. For "visually hidden but read by screen readers" (skip links), use the .sr-only clip pattern — not these.

The framing

"display: none removes the element from the render tree entirely — no box, no space, not in layout, invisible to screen readers and events, and toggling it causes a reflow. visibility: hidden hides it visually but it still occupies its space and stays in the layout — toggling is just a repaint, cheaper. And opacity: 0 is a third: invisible but still takes space and stays interactive and accessible, plus it's the only one that animates smoothly. So: display:none to fully remove, visibility:hidden to hide-but-keep-the-gap, opacity:0 for fades."

Follow-up questions

  • Which is cheaper to toggle and why?
  • When would you specifically want visibility:hidden over display:none?
  • How does opacity:0 differ from both for accessibility and events?
  • How do you visually hide something but keep it readable by screen readers?

Common mistakes

  • Thinking visibility:hidden frees up the space — it doesn't.
  • Using opacity:0 to 'hide' something that's then still clickable by accident.
  • Using display:none/visibility:hidden for content that should still be screen-reader accessible.
  • Not knowing display toggles cause reflow.

Performance considerations

  • display:none toggling triggers reflow (expensive, cascades); visibility:hidden triggers only repaint; opacity changes can be composite-only (GPU, cheapest) — which is why fades animate opacity.

Edge cases

  • A child setting visibility:visible inside a visibility:hidden parent.
  • display:none breaking CSS transitions (can't animate to/from it).
  • opacity:0 elements still capturing clicks, blocking elements behind them.
  • Lazy content inside display:none — images may not load until shown.

Real-world examples

  • Responsive layouts using display:none to hide nav items per breakpoint.
  • visibility:hidden to reserve space for a tooltip; opacity transitions for modal fade-in.

Senior engineer discussion

Seniors give the space/layout distinction, add opacity:0 as the interactive/animatable third option, provide the toggle-cost hierarchy (reflow vs repaint vs composite), and note the accessibility implications and the .sr-only pattern.

Related questions