What is the difference between CSS visibility:hidden and display:none properties? Both CSS rules visibility:hidden and display:none make elements invisible, but are they truly synonymous or do they have distinct behaviors and effects on the layout and rendering of web pages?
The key difference between visibility:hidden and display:none in CSS lies in how they handle layout space and rendering. visibility:hidden makes an element invisible while preserving its position and space in the document flow, whereas display:none completely removes the element from the layout, affecting the positioning of surrounding elements. These properties have distinct impacts on accessibility, performance, and user interaction that make them fundamentally different solutions for hiding content.
Contents
- Fundamental Differences Explained
- Layout and Rendering Behavior
- Accessibility and Screen Reader Impact
- Performance Considerations
- JavaScript Interaction Differences
- Practical Usage Guidelines
- Common Use Cases
Fundamental Differences Explained
The core distinction between visibility:hidden and display:none centers on how they handle element space and rendering in the document flow. When you apply visibility:hidden to an element, the element becomes invisible but continues to occupy the same space it would if it were visible [source]. The browser still renders the element in the layout, making it functionally similar to setting opacity:0 - the content is hidden but the structural space remains intact.
Conversely, display:none completely removes the element from the document flow. The browser renders the page as though the element doesn’t exist at all [source]. This means adjacent elements move to fill the space that would have been occupied by the hidden element, fundamentally changing the page layout. The element effectively becomes non-existent in terms of layout calculations, spacing, and positioning.
Key Insight: Think of
visibility:hiddenas making an element invisible while keeping its seat warm, whiledisplay:noneas if the element never existed in the first place.
Layout and Rendering Behavior
Space Preservation vs Removal
The most significant practical difference is how these properties handle layout space. When using visibility:hidden, the element maintains its dimensions and position in the layout, meaning other elements won’t shift to occupy its space [source]. This is particularly important when you want to temporarily hide content without disturbing the surrounding layout.
With display:none, the element is completely removed from the rendering tree. This causes a reflow of the document as other elements adjust to fill the available space [source]. The layout recalculates as if the element never existed, which can be useful for completely removing elements from the visual hierarchy but can also cause unexpected layout shifts.
Child Element Behavior
Another important distinction is how these properties affect child elements. With visibility:hidden, child elements inherit the visibility property unless explicitly overridden. This means you can have a parent element set to visibility:hidden while specific child elements remain visible by setting their individual visibility to visible [source].
When using display:none, the entire element tree (including all descendants) is removed from rendering. There’s no way to selectively show child elements of a display:none container - they all disappear along with their parent.
/* Visibility allows selective child visibility */
.parent {
visibility: hidden;
}
.parent .child {
visibility: visible; /* This child will remain visible */
}
/* Display removes everything completely */
.parent {
display: none;
}
.parent .child {
visibility: visible; /* This child will still be hidden */
}
Accessibility and Screen Reader Impact
Screen Reader Behavior
Both visibility:hidden and display:none generally hide content from screen readers, but they do so through different mechanisms in the accessibility tree. According to [WebAIM], both properties remove elements from the accessibility tree, making them inaccessible to assistive technologies [source].
However, there are nuanced differences in behavior. As [Marcy Sutton] explains, screen readers utilize the Accessibility Tree, which contains only what’s rendered on screen and is affected by CSS display:none and aria-hidden:true [source]. This means both properties effectively hide content from screen readers, though they achieve this through different internal browser mechanisms.
Interactive Elements and Focus
display:none has a more significant impact on user interaction. Elements with display:none are completely removed from the tab order and cannot receive keyboard focus [source]. This makes them entirely inaccessible to keyboard users.
With visibility:hidden, elements are still present in the DOM and can potentially receive focus, though they remain visually invisible. This creates a confusing experience where users can interact with something they can’t see, which is generally undesirable for accessibility [source].
Performance Considerations
Rendering Performance
Performance differences between these properties become apparent with complex pages and frequent toggling. Elements with display:none are completely excluded from the rendering process, which can lead to better performance when hiding large amounts of content [source]. The browser doesn’t need to calculate styles or perform layout calculations for these elements.
Elements with visibility:hidden are still part of the rendering pipeline. The browser must still process their styles and calculate their positions, even though they’re not visible. This can be less efficient for complex elements, especially when animating or frequently toggling visibility.
Reflows and Repaints
display:none triggers a complete reflow when applied because the element is removed from the document flow. This can cause significant performance impact on pages with many elements or complex layouts [source].
visibility:hidden typically only triggers a repaint since the element’s position and size remain unchanged. This makes it more efficient for situations where you need to frequently toggle visibility without causing layout recalculations.
As one [Reddit discussion] notes, “in cases where an element with a lot of children is hidden using display it can bring better performance than with visibility, because the rendering engine doesn’t have to bother with reflowing and caring about these elements at all” [source].
JavaScript Interaction Differences
DOM Manipulation
Both properties affect JavaScript differently. Elements with display:none are still accessible via DOM methods like querySelector() and can be manipulated through JavaScript [source]. However, attempting to interact with these elements (like focusing buttons) can cause unexpected behavior.
With visibility:hidden, elements remain fully interactive through JavaScript. You can still attach event handlers, manipulate their properties, and perform other DOM operations. However, as one [Stack Overflow discussion] notes, “visibility: hidden performs flawlessly whereas display: none causes clickable buttons to slightly jump upon clicking, as if it tries to show the hidden button for a millisecond” [source].
Dynamic State Changes
JavaScript-driven state changes reveal interesting behavioral differences. When content is initially set to display:none at page load, screen readers typically don’t read it. However, if JavaScript changes the state from visible to display:none, some screen readers may not recognize this change and could continue reading the content [source].
This creates a potential accessibility issue where content might be announced to screen readers even though it’s visually hidden. visibility:hidden behaves more consistently in this regard, though both properties can have unexpected interactions with screen readers when dynamically changed.
Practical Usage Guidelines
When to Use visibility:hidden
Choose visibility:hidden when:
- You need to temporarily hide content without affecting layout
- You want to create smooth transitions for show/hide animations
- You’re working with forms and need to preserve state while hiding elements
- You need to hide content but maintain focus for keyboard navigation (in specific cases)
When to Use display:none
Choose display:none when:
- You need to completely remove elements from the document flow
- You’re building responsive layouts where content should be entirely hidden on certain viewports
- You want to optimize performance by excluding complex elements from rendering
- You’re creating tabs or accordions where content should be completely removed from accessibility when hidden
Best Practices
For accessible hiding when content should remain available to screen readers, consider using a visually hidden class like:
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
This approach keeps content in the accessibility tree while hiding it visually, providing better accessibility than either visibility:hidden or display:none alone [source].
Common Use Cases
visibility:hidden Applications
- Progressive disclosure: Showing tooltips or help text that appears on hover
- Form validation: Temporarily hiding error messages while preserving form layout
- Image galleries: Hiding inactive slides while maintaining carousel structure
- Print styles: Removing specific elements that shouldn’t appear in print while maintaining document structure
display:none Applications
- Responsive navigation: Hiding menu items on mobile devices and replacing with hamburger menu
- Tabbed interfaces: Completely removing inactive tab content to improve performance
- Conditional content: Removing elements based on user preferences or device capabilities
- Performance optimization: Excluding heavy components from rendering when not needed
Understanding these subtle but important differences between visibility:hidden and display:none allows developers to make informed decisions about which property to use in different scenarios, ensuring optimal layout, accessibility, and performance for their web applications.
Conclusion
The differences between visibility:hidden and display:none extend far beyond simple visibility toggling. These properties fundamentally alter how elements interact with the document flow, affect accessibility in different ways, and have distinct performance implications. visibility:hidden preserves layout space and maintains element presence in the DOM, while display:none completely removes elements from rendering and layout calculations. When choosing between them, consider not just visual appearance but also accessibility requirements, performance needs, and how child elements should behave. For most modern web development, understanding these nuanced differences is crucial for creating accessible, performant, and maintainable user interfaces.
Sources
- FreeCodeCamp - CSS display:none and visibility:hidden – What’s the Difference?
- Stack Overflow - What is the difference between visibility:hidden and display:none?
- Tutorial Republic - Difference Between CSS Display and Visibility
- HubSpot Blog - CSS Visibility: Everything You Need to Know
- Bomberbot - CSS display:none vs visibility:hidden: A Comprehensive Guide
- Medium - Difference Between “display: none” vs “visibility: hidden” vs “opacity: 0” in CSS
- W3Schools - CSS The display Property
- Code Entity - Hiding an Element with CSS: Display vs Visibility vs Opacity
- DZone - CSS Hide and Seek: display:none vs visibility:hidden
- DEV Community - Display: None vs Visibility: Hidden
- WebAIM - CSS in Action - Invisible Content Just for Screen Reader Users
- Scott O’Hara - Inclusively Hidden
- Nomensa - How to improve web accessibility by hiding elements
- Bitsofcode - The visibility property isn’t just about visibility
- Zell Liew - A new (and easy) way to hide content accessibly