Back to blog

CSS Display None vs Visibility Hidden: Impact on Layout and DOM Accessibility

Hiding elements dynamically is a common requirement when building interactive user interfaces (such as toggling menus, modal windows, or loading states).

In CSS, developers primarily rely on two styling declarations to hide elements: display: none and visibility: hidden.

While both properties render the target element invisible to the user, they handle page layout space, browser rendering calculations, CSS transition animations, and screen reader accessibility differently.

In this guide, we will compare display: none and visibility: hidden, examine their performance footprint, and configure accessible layouts.

1. display: none (No Space Occupied)

The display: none declaration completely removes the element from the browser's Render Tree.

  • Space Occupancy: The element occupies zero space on the page. It is treated as if it does not exist in the DOM layout. Surrounding elements dynamically collapse and shift to fill the gap left by the hidden element.
  • Browser Rendering Cost: Toggling this property forces the browser to recalculate the positions of elements on the entire page. This triggers a Reflow (Layout) followed by a Repaint, which can be computationally expensive on complex pages.
.hidden-box {
  display: none; /* Completely invisible, takes 0px space */
}

2. visibility: hidden (Space Occupied)

The visibility: hidden declaration makes the element invisible, but preserves its position in the document flow.

  • Space Occupancy: The element remains in the Render Tree and continues to occupy its original physical space (width and height). It acts as an invisible box; surrounding elements remain in their positions and do not collapse.
  • Browser Rendering Cost: Toggling this property does not affect page layouts. The browser only updates the element's paint state. It triggers a Repaint but bypasses the expensive Reflow stage, resulting in faster rendering performance.
.invisible-box {
  visibility: hidden; /* Invisible, but keeps its layout box dimensions */
}

CSS Transition Animations Support

Creating smooth fade-out or slide-down animations requires CSS transitions.

  • display: none cannot be animated: Because display is a binary layout property (the box is either in the layout tree or it is not), you cannot transition from display: block to display: none. The element will snap out of existence instantly, ignoring opacity settings.
  • visibility: hidden supports transitions: You can transition the visibility property. Combined with opacity, you can create smooth fade transitions. The element remains interactive during the fade and becomes completely non-interactive once the visibility timer finishes:
.modal {
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.modal.active {
  visibility: visible;
  opacity: 1;
}

The Accessibility Trap (Screen Readers)

A common mistake is using these properties to hide content that should still be read aloud by screen readers (such as label text for form inputs lacking visual placeholders).

Both display: none and visibility: hidden instruct screen readers to completely ignore the element. The hidden content will not be announced to visually impaired users.

The Solution: sr-only (Screen Reader Only) Class

To hide elements visually while preserving screen reader accessibility, use absolute positioning offsets to move the element off-screen:

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

Features Comparison Matrix

Feature display: none visibility: hidden
Occupies Page Space? No Yes (acts as invisible block)
Triggers Reflow (Layout)? Yes No (triggers Repaint only)
Transitions support? No Yes (when combined with opacity)
DOM Events interaction? No (cannot receive clicks) No (cannot receive clicks)
Read by Screen Readers? No No

Conclusion

Choose display: none when you need to hide elements completely and collapse the surrounding layout (like closing alerts or hiding dashboard panels). Use visibility: hidden when you need to preserve the layout structure (avoiding page jumps) or want to apply smooth CSS fade transitions. For accessibility labels, use the .sr-only class technique to hide elements visually without blocking screen readers.