Get Ready For Display Contents

A comprehensive guide to understanding CSS display: contents, its practical applications, browser support, and critical accessibility considerations for modern web development.

Introduction: The Disappearing Box

Every web developer has faced this scenario: you're building a layout with CSS Grid or Flexbox, and suddenly you need to nest elements for organizational purposes--but those wrapper elements are interfering with your carefully planned grid structure. The children refuse to align properly because some parent div is throwing off your calculations. You need those wrapper elements for semantic HTML or component organization, but you don't want them to participate in the layout.

This is exactly the problem display: contents was designed to solve. When you apply this CSS property to an element, the browser effectively makes that element disappear from the layout entirely--its children are "promoted" to appear as if they were direct children of the element's parent. The wrapper box is removed from the rendering tree, leaving only its contents to participate in layout as if the wrapper never existed.

The concept sounds elegant and powerful. On paper, display: contents offers the ability to have your markup cake and eat it too--keeping your HTML semantically meaningful and structurally organized while giving CSS complete control over how elements actually lay out. However, as we'll explore in this guide, this seemingly simple property comes with significant caveats that every modern web developer needs to understand before using it in production.

What This Guide Covers

This guide provides a comprehensive exploration of display: contents, examining its technical mechanics, practical applications, and critically, its accessibility implications. We'll look at real-world use cases where it can be beneficial, but we'll also give honest attention to the documented issues that have caused many accessibility experts to recommend avoiding this property altogether. By the end, you'll understand not just how display: contents works, but whether you should use it in your projects.

[Learn more about modern CSS layout techniques with our CSS Grid guide and Flexbox best practices. MDN Web Docs - CSS display property provides complete technical reference for this CSS feature.]

How Display Contents Works

Understanding the Box Tree

To understand display: contents, you need to understand how browsers construct what the CSS specification calls the "box tree." When a browser renders an HTML document, it doesn't just directly translate DOM elements into visible boxes. Instead, it creates an intermediary structure: every element generates one or more boxes, and these boxes form a hierarchy that determines how content is laid out and rendered.

Normally, this box tree mirrors the DOM tree structure. A div element with three child divs generates a parent box that contains three child boxes. The CSS display property controls what kind of box each element generates. A div with display: block generates a block-level box, while a span with display: inline generates an inline box. When you use display: flex or display: grid, you're telling the browser to use a different layout algorithm for the children of that box.

The key insight is that display: contents fundamentally alters this box tree generation process. According to the CSS Display specification, when an element has display: contents applied, the element itself generates no box at all. Instead, the element's children are treated as if they are direct children of the element's parent box. The "wrapper" element vanishes, leaving only its children to participate in layout.

Syntax and Basic Usage

.wrapper {
 display: contents;
}

Or in your HTML:

<div class="grid-container">
 <div class="wrapper">
 <div class="item">Item 1</div>
 <div class="item">Item 2</div>
 <div class="item">Item 3</div>
 </div>
 <div class="item">Item 4</div>
 <div class="item">Item 5</div>
</div>

In this example, without display: contents, the .wrapper div would interfere with the grid layout, potentially creating unwanted spacing or alignment issues. But when .wrapper has display: contents, the browser ignores it entirely during layout calculation. The three items inside become direct children of .grid-container, behaving exactly as if the .wrapper div didn't exist.

It's important to note that while the element is removed from the visual and layout rendering, it still exists in the DOM. JavaScript can still select it, event listeners attached to it still function, and it remains part of the document structure for purposes like printing or PDF generation. The element is only "invisible" to the CSS layout engine.

What Properties Still Apply

When an element has display: contents applied, most layout-related properties are effectively ignored because there's no box to apply them to. Properties like width, height, margin, padding, and border no longer produce any visible effect because the element generates no box that could receive those styles.

However, some properties still have an effect. If an element with display: contents has opacity applied, that opacity still affects its descendants because opacity is inherited through the DOM tree. Similarly, CSS transforms applied to a display: contents element won't affect the layout, but they will transform the rendered position of any absolutely positioned descendants.

One particularly tricky area is counters and generated content. CSS counters defined on an element with display: contents still apply to descendants, which can lead to unexpected behavior if you're relying on counter scoping. Pseudo-elements (::before and ::after) on elements with display: contents are also not generated, since there's no box to attach them to.

[Explore how display: contents compares to other CSS layout techniques in our comprehensive CSS layout guide. For advanced CSS optimization strategies, see our guide on CSS performance optimization. MDN Web Docs - CSS display property]

Practical Use Cases

Common scenarios where display: contents can solve layout challenges

CSS Grid Layouts

Keep semantic card components while allowing their children to participate directly in grid layout without wrapper interference.

Flexbox Grouping

Group related navigation items semantically while allowing all links to flow together in a single flex line.

Semantic HTML Without Penalty

Use article, section, aside, and nav elements without suffering block-level layout interference.

Component Architecture

Maintain component boundaries for styling and JavaScript while letting CSS treat children as direct descendants.

CSS Grid Layout Example
1.card-grid {2 display: grid;3 grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));4 gap: 2rem;5}6 7.card {8 display: contents;9}10 11/* Card sections become direct children of .card-grid */12.card-header,13.card-body,14.card-footer {15 /* Styling for card sections */16}

Browser Support Overview

95.85%

Global browser support coverage

10.52%

Full support

85.33%

Partial support (with known issues)

IE

No support (never supported)

Accessibility Concerns

The Core Problem

This section is critically important. While display: contents is an elegant solution to certain layout problems, it has a long and troubled history with accessibility. The fundamental issue is that when an element has display: contents applied, browsers historically removed not just the visual box but also the semantic information that assistive technology relies on.

As accessibility expert Eric Bailey documents extensively, applying display: contents to certain elements can "prevent buttons from being announced as buttons, tables as being announced and navigated as tables, lists as being announced and navigated as lists." In other words, when display: contents works as designed visually, it can simultaneously break the semantic announcements that screen reader users depend on.

This isn't a minor inconvenience--it's a fundamental breakdown of the accessibility contract. When Adrian Roselli and other accessibility practitioners discovered these issues, they documented them thoroughly and advocated for browser vendors to fix the problems. Fixes were implemented, but then regressions occurred. Browser updates would re-introduce the bugs, breaking accessibility for users who had relied on the property working correctly.

Known Problematic Elements

Research and testing have identified several element types that are particularly problematic when display: contents is applied:

Buttons - When a <button> element or any element with role="button" has display: contents applied, it may not be announced as a button to screen reader users. This issue has been documented in Chromium, Firefox, and WebKit browsers with ongoing fixes not fully resolving the problem.

Tables and Table-Like Elements - Elements with ARIA roles directory, grid, treegrid, table, row, gridcell, cell, columnheader, tree, and treeitem have accessibility issues when display: contents is applied.

Interactive Elements - Links, form inputs, and other interactive elements may lose their semantic meaning when wrapped in a display: contents element, causing users of assistive technology to miss important functionality.

The Regression Problem

What makes the accessibility situation particularly concerning is the pattern of regressions. Browser vendors have fixed these issues multiple times, only for subsequent browser updates to re-introduce the bugs. As Bailey notes, this creates a "game of Whac-A-Mole" where accessibility practitioners cannot trust that a property working correctly today will continue to work tomorrow.

[Learn about building accessible web applications with our web accessibility guide. For comprehensive CSS accessibility patterns, see our guide on CSS accessibility fundamentals. Eric Bailey - display: contents considered harmful]

Browser Support Timeline for display: contents
BrowserFirst SupportCurrent StatusKey Notes
Chromev65 (2018)Partial supportAccessibility bugs in earlier versions
Firefoxv37 (2015)Partial supportIssues persisted until v62+
Safariv11.1 (2018)Partial supportWorst history of accessibility bugs
Edgev79 (2020)Partial supportChromium-based, follows Chrome
IENeverNot supportedNo support planned
iOS Safariv17 (2023)Full supportRecent improvement from partial
Chrome for Androidv143+Partial supportSimilar to desktop Chrome

Best Practices and Recommendations

Current Industry Stance

Given the documented history of accessibility issues and ongoing concerns, many accessibility practitioners recommend avoiding display: contents entirely in production code. The position isn't that the property is fundamentally broken, but that the pattern of regressions and the difficulty of testing across all assistive technology combinations makes it an unpredictable choice.

Eric Bailey's conclusion reflects this sentiment: "At this point, I don't think we as an industry can use display: contents with confidence. Past actions are a good indicator of future behavior, and the road to hell is paved with good intentions."

When It Might Be Acceptable

Despite the concerns, there may be situations where using display: contents is acceptable:

Non-Interactive Content - If you're applying display: contents to wrapper elements that contain only static text, images, or other non-interactive content, the risk of breaking accessibility is lower.

Internal Tools - Applications or tools where you control both the browser environment and can verify accessibility manually may be appropriate candidates for display: contents use.

Progressive Enhancement - If you can structure your code so that content is fully accessible without display: contents, and the property is used purely for visual improvements, the risk profile changes.

Safer Alternatives

Before reaching for display: contents, consider these alternatives that don't carry the same accessibility concerns:

Adjust HTML Structure - If at all possible, restructuring your HTML to avoid the need for display: contents is the safest approach.

CSS Grid Without Wrappers - Modern CSS Grid makes it easier to create complex layouts without needing wrapper elements for grouping. Using named areas or specific line-based placement can often eliminate the need for wrapper divs.

margin: 0 on Wrappers - If you need wrapper elements for organizational purposes but want them to not affect layout, simply removing margins, padding, and borders from the wrapper can often solve the same problems without using display: contents:

.wrapper {
 margin: 0;
 padding: 0;
 border: none;
}

HTML-over-the-Wire Approaches - If you're using a modern framework, consider whether component composition can solve the layout problem at the framework level rather than using CSS to make elements disappear.

Testing Requirements

If you do use display: contents, thorough testing is essential:

  • Screen reader testing with NVDA, JAWS, VoiceOver, TalkBack
  • Keyboard navigation verification
  • Cross-browser testing across all major engines
  • Ongoing monitoring for browser update regressions

[Discover modern CSS frameworks and tools in our technologies overview for frontend development. For building maintainable CSS architectures, see our guide on CSS architecture best practices. Can I Use - CSS display: contents]

Progressive Enhancement Pattern with Fallback
1.layout-grid {2 display: flex;3 flex-wrap: wrap;4 gap: 1rem;5}6 7/* Fallback for browsers without display:contents support */8.layout-grid > .group {9 flex: 1 1 300px;10}11 12@supports (display: contents) {13 .layout-grid > .group {14 display: contents;15 }16 17 .layout-grid > .group > * {18 /* These become direct children of .layout-grid */19 }20}

Frequently Asked Questions

Conclusion

display: contents is a fascinating CSS property that solves a real problem: the mismatch between semantic HTML structure and CSS layout requirements. Its ability to make wrapper elements "invisible" to the layout engine while keeping them in the DOM is technically impressive and can simplify certain layout challenges.

However, the extensive accessibility issues documented over the years--and the pattern of regressions where browser updates re-introduce fixed bugs--make this property a calculated risk. For production websites serving broad audiences, especially in enterprise or accessibility-critical contexts, the safer approach is often to restructure HTML or use other CSS techniques.

If you do choose to use display: contents, understand that you're accepting responsibility for ongoing testing across browsers and assistive technologies. The property might work correctly today, but tomorrow's browser update could change that. Budget accordingly, test thoroughly, and have a plan for responding if accessibility issues emerge.

For many projects, the recommendation is simple: don't use display: contents in production. The potential accessibility impact on users isn't worth the convenience of cleaner CSS layouts. There are usually alternative approaches--sometimes requiring more HTML restructuring, sometimes requiring creative CSS--that achieve similar visual results without the same risk profile.

The web platform is built on progressive enhancement and graceful degradation. When a CSS property has documented accessibility issues that have proven difficult for browser vendors to resolve consistently, the progressive enhancement approach is to use properties that are known to work reliably for all users.

[Explore our web development services to build accessible, performant websites. Contact our team to discuss how we can help you implement modern CSS techniques while maintaining excellent accessibility standards.]

Ready to Build Better Web Experiences?

Our team specializes in modern web development with a focus on accessibility, performance, and maintainability.

Sources

  1. MDN Web Docs - CSS display property - Official CSS reference for display property syntax, values, and usage
  2. Can I Use - CSS display: contents - Browser support data and accessibility bug notes for display:contents
  3. Eric Bailey - display: contents considered harmful - Accessibility expert analysis of display:contents issues
  4. LogRocket - Exploring the CSS display property - Deep dive tutorial covering display property values and practical examples