How Does display: none Differ From visibility: hidden?

While both display: none and visibility: hidden hide elements on a webpage, they handle document layout, performance, user interaction, and accessibility in fundamentally different ways. The primary distinction lies in space allocation: display: none removes the element entirely from the document flow as if it does not exist, whereas visibility: hidden hides the element visually while preserving its physical dimensions and position on the page.

Document Flow and Layout Space

The most immediate visual difference between the two properties is how the surrounding content responds:

  • display: none: The browser removes the element from the layout flow. Adjacent elements shift to fill the vacated space. The element occupies zero width and zero height in the rendering calculation.
  • visibility: hidden: The element becomes completely transparent, but its bounding box remains intact. An empty blank space remains where the element was rendered, preventing surrounding content from shifting or reflowing.

DOM Presence and the Render Tree

Both properties leave the affected HTML elements inside the Document Object Model (DOM), meaning JavaScript can still query and manipulate them using methods like document.querySelector(). However, their treatment in browser rendering engines differs:

  • display: none: The element is excluded from the browser's render tree. Applying or removing display: none triggers a full reflow (layout recalculation) and a repaint, which can be computationally expensive on complex layouts.
  • visibility: hidden: The element remains in the render tree. Changing visibility triggers only a repaint because the dimensions and coordinates are already calculated and remain fixed.

Inheritance and Child Elements

The behavior of nested child elements differs significantly between the two rules:

  • display: none: Non-overridable by children. If a parent element has display: none, setting display: block or any other display value on a descendant element will not make the child visible.
  • visibility: hidden: Inherited, but overridable. If a parent element has visibility: hidden, any child element with visibility: visible explicitly declared will render normally on the screen, even while the parent remains invisible.

User Interaction and Event Listeners

Hiding an element also changes how user inputs and pointer interactions are processed:

  • display: none: The element cannot receive focus, be clicked, hovered, or trigger any mouse or pointer events.
  • visibility: hidden: Pointer events are disabled by default. Clicking or hovering over the reserved blank space will not trigger click or hover handlers on the hidden element.

CSS Transitions and Animations

When building UI animations, each property provides different levels of support:

  • display: none: Cannot be transitioned smoothly using CSS transitions. The browser switches abruptly between states because display is a discrete, non-interpolatable property.
  • visibility: hidden: Can be combined with CSS transitions and opacity to create smooth fade-in and fade-out effects, allowing the visibility change to delay until an opacity transition completes.

Accessibility and Screen Readers

Neither property is intended for creating accessible, visually-hidden content (such as screen-reader-only labels):

  • display: none: Ignored by assistive technologies. Screen readers skip the element and all its children completely.
  • visibility: hidden: Also removed from the accessibility tree in modern browsers, meaning screen readers will generally ignore the hidden element despite its physical layout footprint.

Quick Comparison

Feature display: none visibility: hidden
Layout Space Collapsed (takes no space) Preserved (leaves blank space)
Render Tree Excluded Included
Child Overrides Cannot be made visible Children can use visibility: visible
Browser Performance Triggers reflow and repaint Triggers repaint only
CSS Transitions Not animatable Supports transition delays
Accessibility Tree Removed completely Removed completely