Every web developer faces the challenge of showing and hiding elements. Whether building accordions, modals, tabs, or conditional content, understanding how to hide and reveal divs properly is fundamental to creating interactive, performant websites. This guide covers every CSS technique for hiding elements, from the basic display property to the modern content-visibility API, with practical code examples you can use in your Next.js projects today.
Why Hiding Elements Matters
Proper element hiding is crucial for modern web interfaces. Whether you're building modals that overlay content, dropdown menus that appear on hover, accordions that reveal additional information, or responsive designs that adapt to different screen sizes, controlling visibility is fundamental.
Modals and dialogs require complete removal from the layout when hidden to prevent screen readers from accessing invisible content. Dropdown menus benefit from techniques that preserve layout space to prevent content jumping when they appear. Responsive designs frequently show or hide navigation elements, sidebars, or supplementary content based on viewport width.
The technique you choose impacts three critical areas: performance (how quickly your page renders), accessibility (whether assistive technologies can interact with your content), and user experience (smooth transitions and intuitive interactions). MDN Web Docs provides comprehensive guidance on accessible CSS hiding techniques that balance these concerns.
For interactive components like accordions and tabs, the choice of visibility control determines whether users experience smooth animated transitions or jarring instant changes. Performance considerations become especially important on long pages with many hidden sections, where inefficient hiding techniques can significantly impact initial render time and scrolling performance across all devices. Implementing proper visibility control is a key aspect of professional web development that distinguishes well-built applications from hastily assembled interfaces.
The display Property: Complete Removal
The display: none property is the most common and fundamental way to hide HTML elements. When applied, the element is completely removed from the document flow--no space is reserved in the layout, the browser doesn't render it, and screen readers cannot access its content.
This makes display: none ideal for scenarios where you want content to truly not exist from a layout and accessibility perspective. According to GeeksforGeeks, this property is part of nine distinct CSS techniques for hiding elements, but it remains the most widely used due to its simplicity and complete removal behavior.
Basic Syntax
.hidden {
display: none;
}
JavaScript Toggle Patterns
const toggleVisibility = () => {
const element = document.getElementById('myDiv');
if (element.style.display === 'none') {
element.style.display = 'block';
} else {
element.style.display = 'none';
}
};
React and Next.js Pattern
const [isVisible, setIsVisible] = useState(false);
return (
<div>
<button onClick={() => setIsVisible(!isVisible)}>
{isVisible ? 'Hide' : 'Show'}
</button>
<div style={{ display: isVisible ? 'block' : 'none' }}>
This content is conditionally visible.
</div>
</div>
);
Limitations
The display: none property cannot be animated directly, making it unsuitable for smooth transitions. When toggled, it causes layout shifts as content appears or disappears from the document flow. For animated visibility changes, consider using opacity with transitions instead. Additionally, screen readers will not announce content hidden with display: none, which is the intended behavior for truly hidden content but requires consideration when you want visually hidden but accessible content.
The visibility Property: Hidden but Reserving Space
The visibility: hidden property offers an alternative approach that hides an element while preserving its space in the layout. The element remains in the DOM and the accessibility tree but is simply invisible to users. MDN Web Docs confirms that content hidden with visibility: hidden is inaccessible to screen readers, just as it is with display: none.
This technique is valuable when you want to maintain layout stability while hiding content. The space previously occupied by the element remains reserved, preventing layout shifts that could confuse users or disrupt the visual hierarchy.
.invisible {
visibility: hidden;
}
.visible {
visibility: visible;
}
When to Use visibility
The visibility property shines in scenarios where you need consistent layout spacing. Accordions, for example, benefit from visibility hiding because the collapsed state maintains the space that will be occupied when expanded. This prevents the surrounding content from jumping around as users interact with the interface.
Unlike display: none, visibility: hidden cannot receive focus or user interaction, which aligns with the goal of hiding content from users. However, the element still exists in the page, meaning some rendering overhead remains even when invisible.
| Property | Layout Space | Rendered | Screen Reader | Animatable |
|---|---|---|---|---|
| display: none | No | No | No | No |
| visibility: hidden | Yes | No | No | No |
| opacity: 0 | Yes | Yes | Yes | Yes |
| content-visibility: hidden | Yes | No | No | No |
The opacity Property: Invisible but Interactive
Setting opacity: 0 creates a unique hiding technique where the element remains fully interactive and accessible while being visually invisible. The element continues to receive all user interactions, maintains its layout space, and participates in the accessibility tree.
This approach is ideal for smooth fade transitions and interactive reveal effects where you want users to interact with the hidden element without visual clutter. GeeksforGeeks documents opacity as one of the key CSS properties for hiding elements, valued for its animation capabilities.
.fade-element {
opacity: 1;
transition: opacity 0.3s ease;
}
.fade-element.hidden {
opacity: 0;
pointer-events: none;
}
Performance Considerations
Opacity changes trigger repaints and can be GPU-intensive, especially for complex elements or when animating on low-end devices. Unlike display: none, which has zero render cost when hidden, opacity: 0 requires the browser to continue rendering the element at full resolution--it's simply rendered invisibly.
For this reason, combine opacity hiding with pointer-events: none to prevent the invisible element from capturing mouse events. This is particularly important for overlay elements, dropdown menus, and any hidden content that might interfere with user interactions when it should be inaccessible.
Use Cases
Opacity-based hiding excels in scenarios requiring smooth transitions: hover reveal effects, loading spinners that fade out, modal overlays that fade in gradually, and any interactive element where users benefit from visual feedback during visibility changes. Always respect prefers-reduced-motion when implementing opacity animations to accommodate users who experience motion sensitivity. These animation techniques are essential for creating polished user interfaces in modern web applications.
Modern CSS: content-visibility Property
The content-visibility property represents the modern approach to controlling element visibility with a focus on performance. Introduced as part of the CSS Containment specification, it allows browsers to skip rendering work for off-screen content, potentially improving page load times by up to 7x according to web.dev performance testing.
Browser Support: Chrome 85+, Edge 85+, Firefox 125+, Safari 18+
content-visibility: auto
When set to auto, the browser applies layout, style, and paint containment to the element. If the element is off-screen, the browser skips rendering entirely until it enters the viewport. This dramatically reduces initial render time for long pages with many sections.
.lazy-section {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}
contain-intrinsic-size Explained
The contain-intrinsic-size property is essential when using content-visibility. It tells the browser what size to use for the element when calculating layout, preventing scrollbar jumping when content loads. Without it, the browser doesn't know the element's dimensions and may miscalculate the scrollable area.
content-visibility: hidden
Similar to display: none but with a key difference: the browser maintains the cached rendering state. This can be useful for conditionally revealing content without losing rendering work, though display: none remains the better choice for truly hidden content.
Performance Impact
According to web.dev, pages using content-visibility: auto showed a 50% reduction in initial render time and up to 7x improvement in time to interactive for pages with significant off-screen content. This makes it particularly valuable for resource-heavy pages with accordions, tabs, or conditionally rendered sections. Optimizing rendering performance through techniques like content-visibility is a core component of performance optimization for production web applications.
Performance Impact by Technique
0
Render cost for display:none
7x
Improvement with content-visibility:auto
50%
Reduction in initial render time
GPU
Opacity rendering requirement
Accessibility Considerations
When hiding content, you must consider how assistive technologies will interact with your interface. WCAG guidelines provide important requirements for accessible visibility control. The MDN Web Docs accessibility guide emphasizes that different hiding techniques have distinct impacts on assistive technology behavior.
Screen Reader Behavior
Different hiding techniques have different impacts on screen readers:
display: noneandvisibility: hiddenmake content inaccessible to screen readersopacity: 0keeps content accessible but invisible- Use
aria-hidden="true"for visual-only content that should be hidden from assistive technology while remaining in the DOM
Focus Management
Proper focus management is critical when showing hidden content. When opening a modal, move focus to the modal container. When closing, return focus to the trigger element that opened it. Always trap focus within modals to prevent users from navigating outside while the modal is open.
Accessible Tabs Example
const [activeTab, setActiveTab] = useState(0);
return (
<div role="tablist">
{tabs.map((tab, index) => (
<button
role="tab"
aria-selected={activeTab === index}
aria-controls={`panel-${index}`}
id={`tab-${index}`}
onClick={() => setActiveTab(index)}
>
{tab.label}
</button>
))}
</div>
<div>
{tabs.map((tab, index) => (
<div
role="tabpanel"
id={`panel-${index}`}
aria-labelledby={`tab-${index}`}
hidden={activeTab !== index}
>
{tab.content}
</div>
))}
</div>
);
This pattern uses proper ARIA roles, manages focus states, and ensures screen readers announce content changes appropriately. Always test your accessible implementations with actual screen reader software to verify the user experience. Building accessible interfaces is a fundamental requirement of professional web development services that ensures your applications work for all users.
JavaScript Integration Patterns
Modern web applications require robust JavaScript patterns for controlling element visibility. Here are practical implementations for vanilla JavaScript and React/Next.js applications that you can integrate into your projects today.
Vanilla JavaScript Toggle Controller
class ToggleController {
constructor(selector) {
this.element = document.querySelector(selector);
this.isVisible = true;
}
hide() {
this.element.style.display = 'none';
this.isVisible = false;
}
show(displayType = 'block') {
this.element.style.display = displayType;
this.isVisible = true;
}
toggle() {
if (this.isVisible) {
this.hide();
} else {
this.show();
}
return this.isVisible;
}
// Static method for inline handlers
static toggleById(id, displayType = 'block') {
const element = document.getElementById(id);
if (element) {
const isHidden = element.style.display === 'none';
element.style.display = isHidden ? displayType : 'none';
}
}
}
React Custom Hook
const useToggle = (initialState = false) => {
const [isVisible, setIsVisible] = useState(initialState);
const show = useCallback(() => setIsVisible(true), []);
const hide = useCallback(() => setIsVisible(false), []);
const toggle = useCallback(() => setIsVisible(v => !v), []);
return { isVisible, show, hide, toggle };
};
// Usage in component
const MyComponent = () => {
const { isVisible, toggle } = useToggle(false);
return (
<div>
<button onClick={toggle}>{isVisible ? 'Hide' : 'Show'}</button>
{isVisible && <div>Visible content</div>}
</div>
);
};
Event-Driven Visibility Control
// Dropdown toggle with outside click detection
document.addEventListener('click', (e) => {
const dropdown = document.getElementById('dropdown');
const toggle = document.getElementById('dropdown-toggle');
if (!dropdown.contains(e.target) && !toggle.contains(e.target)) {
dropdown.style.visibility = 'hidden';
}
});
// Intersection Observer for content-visibility triggers
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.contentVisibility = 'visible';
observer.unobserve(entry.target);
}
});
});
document.querySelectorAll('.lazy-load').forEach(el => {
observer.observe(el);
});
These patterns provide reusable, maintainable approaches to visibility control that integrate seamlessly with modern frameworks and vanilla JavaScript applications.
Best Practices Summary
- Choose the right technique for the job -
displayfor complete removal,visibilityfor layout stability,opacityfor animations - Consider performance - Use
content-visibilityfor long pages and lazy loading improvements - Maintain accessibility - Ensure hidden content is inaccessible to assistive technology when appropriate
- Manage focus - When revealing content, ensure focus moves to appropriate elements
- Animate responsibly - Use opacity for smooth transitions, respect
prefers-reduced-motion - Test on real devices - Performance characteristics vary across browsers and devices
Quick Reference Table
| Scenario | Recommended Technique |
|---|---|
| Modal dialogs | display: none + focus trap |
| Accordions | visibility + height transition |
| Dropdown menus | visibility + opacity transition |
| Lazy loading | content-visibility: auto |
| Fade effects | opacity with transitions |
| Conditional content | display: none |
Following these guidelines will help you build interfaces that perform well, work with assistive technologies, and provide smooth user experiences across all devices and browsers.
Conclusion
Mastering CSS visibility control is essential for building modern, performant, and accessible web interfaces. By understanding the trade-offs between display, visibility, opacity, and the modern content-visibility property, you can make informed decisions that improve both performance and user experience.
Remember these key principles:
- Use
display: nonewhen you want complete removal from layout and accessibility - Use
visibility: hiddenwhen you need to maintain layout space - Use
opacitywhen smooth transitions are required - Use
content-visibilityto optimize rendering performance for long pages - Always consider accessibility implications when hiding content
- Implement proper focus management for dynamically shown elements
With these techniques in your toolkit, you can build responsive, accessible, and performant interfaces that work seamlessly across all devices and browsers.
Implementing proper visibility control is just one aspect of building high-quality web applications. If you need assistance with your web development projects or want to optimize your existing interfaces, our team at Digital Thrive can help you implement these best practices and more. Contact us today to discuss how our web development expertise can elevate your projects.
Frequently Asked Questions
Can I animate display: none?
No, display: none cannot be animated directly. For animated visibility changes, use opacity with transitions or CSS keyframe animations that modify display after the animation completes.
What is the difference between visibility: hidden and display: none?
visibility: hidden hides the element but preserves its space in the layout, while display: none completely removes the element from the document flow and frees up its space.
Is content-visibility supported in all browsers?
content-visibility is supported in Chrome 85+, Edge 85+, Firefox 125+, and Safari 18+. For older browsers, use feature detection or provide fallbacks.
How do I hide content from screen readers?
Use display: none or visibility: hidden to hide content from screen readers. You can also use aria-hidden="true" on individual elements without changing their visual appearance.
Which hiding method is most performant?
display: none has zero render cost when hidden. content-visibility: auto provides significant performance benefits for long pages by skipping off-screen content rendering.