Testing

CSS display contents: Browser Support, Use Cases, Issues

CSS display: contents removes a wrapper's box but keeps its children. Works in Chrome 65+, Firefox 37+, Safari 11.1+, Edge 79+. See use cases and a11y issues.

Author

Prince Dewani

May 6, 2026

CSS display: contents is a value of the CSS display property that removes an element's box from layout while keeping its children rendered as direct descendants of the parent. It works in Chrome 65+, Edge 79+, Firefox 37+, Safari 11.1+, iOS Safari 11.3+, Opera 52+, and Samsung Internet 9.2+, while Internet Explorer never added support.

This guide covers what display: contents is, the browsers that support it, the use cases, the known issues, and how to check browser support.

What is CSS display: contents?

CSS display: contents is a value of the display property defined in the W3C CSS Display Module Level 3 specification. The element itself produces no box, so its border, background, padding, width, and height are ignored, while its children and pseudo-elements still render and join the parent's flex or grid container.

Which browsers does CSS display: contents support?

CSS display: contents works in every major modern browser, with global support around 95%. The version where it first shipped, and any accessibility caveats, vary by engine.

Loading browser compatibility data...

CSS display: contents compatibility in Chrome

Chrome supports display: contents from Chrome 65 on Windows, macOS, Linux, ChromeOS, and Android. Chrome 58 to 64 had the value behind the Experimental Web Platform features flag, and Chrome 4 to 57 did not support it. The accessibility-tree regression that stripped roles from list and button wrappers was fixed in Chrome 89, so use Chrome 89 or later as the practical floor for screen-reader-safe usage.

CSS display: contents compatibility in Edge

Microsoft Edge supports display: contents from Edge 79 on Windows, macOS, and Linux, when Edge moved to the Chromium engine. Legacy EdgeHTML 12 to 18 did not support the value at all. Chromium-based Edge inherits every Chrome fix, including the accessibility-role preservation, from Edge 89 on.

CSS display: contents compatibility in Firefox

Firefox supports display: contents from Firefox 37 on Windows, macOS, Linux, and Android. Firefox 2 to 36 did not support it. Firefox 61 had a known bug that demoted ul, ol, and dl elements to a generic text-leaf role in the accessibility tree, and Firefox 62 fixed the regression so list semantics survive on every supported version.

CSS display: contents compatibility in Safari

Safari supports display: contents from Safari 11.1 on macOS High Sierra and from iOS Safari 11.3 on iPhone and iPad. Safari 3.1 to 11 on macOS and iOS Safari 3.2 to 11.2 did not support the value. The WebKit accessibility-tree regression tracked under bug 185679 was resolved in Safari 16 on macOS Ventura, with iOS Safari 17 reaching full accessibility-safe support.

CSS display: contents compatibility in Opera

Opera supports display: contents from Opera 52 on Windows, macOS, and Linux, with Opera 9 to 51 not supporting it. Chromium-based Opera tracks every Chrome fix, including the accessibility-role preservation that landed alongside Chrome 89. Opera Mini renders a server-rendered preview and does not support display: contents at all.

CSS display: contents compatibility in Samsung Internet

Samsung Internet supports display: contents from Samsung Internet 9.2 on Galaxy phones and tablets. Samsung Internet 4 to 8.2 did not support it. The browser inherits the Chromium accessibility fix that shipped in Chrome 89, which lands in Samsung Internet 14 and later. Older Samsung Internet builds still drop list and button roles when display: contents is applied.

CSS display: contents compatibility in Android Browser

Modern Chrome for Android supports display: contents from Chrome 65 on Android 4.4 and later. The legacy stock Android Browser shipped on Android 2.1 to 4.4.4 never implemented the value, so the wrapper keeps its default box on those versions. Chrome for Android, Samsung Internet, and Firefox for Android all inherit their desktop engine's display: contents support and accessibility behavior.

CSS display: contents compatibility in Internet Explorer

Internet Explorer 5.5 through 11 never implemented display: contents, so the declaration is treated as invalid and the wrapper keeps its default block or inline box. Microsoft has retired Internet Explorer, so move IE-only layouts to Chromium Edge or use a wrapper-based fallback that does not depend on the property at all.

Note

Note: display: contents breaks across older Safari, Firefox, and Chromium versions because each engine ships a different accessibility-tree fix. Test it on real browsers and OS with TestMu AI. Try TestMu AI free!

What are the use cases of CSS display: contents?

display: contents shines whenever a wrapper element exists for HTML or component reasons but should not break a flex or grid layout. The property lets the wrapper stay in the markup while its children act as direct grid or flex items.

  • Promote nested children to grid items: Wrap a group of cards inside a section or article tag for semantics, then set the wrapper to display: contents so the cards line up on the parent grid's tracks instead of getting trapped in a separate sub-container.
  • Style components from a third-party framework: When a UI library outputs an extra wrapping div around its slot, display: contents hides the wrapper from layout so your CSS Grid or Flexbox parent can address the inner content directly without a fork or override.
  • Subgrid alternative for flex layouts: Subgrid solves the alignment problem for grid containers, but flex containers cannot use it. display: contents on intermediate wrappers is the closest substitute when you want grandchildren to align with the flex parent's items.
  • Conditional layout collapse: Toggling a wrapper between display: block and display: contents lets the same markup render as a grouped card on small screens and as a flat row of children on large screens, with no DOM swap and no JavaScript reflow cost.
  • Server-rendered list normalization: Server frameworks often emit a ul wrapper around a single li even when the surrounding grid expects flat rows. display: contents on the ul keeps the list semantics for assistive tech on modern browsers and lets the li participate in the grid.
  • Tailwind CSS contents utility: Tailwind ships a contents class that compiles to display: contents, so designers can apply the behavior straight from a class attribute without writing custom CSS.
...

What are the known issues with CSS display: contents?

CSS display: contents has a thin set of known issues that all trace back to one root: browsers historically tied semantics to the box, not to the element. Modern engines have fixed most of the bugs, but legacy versions still surface them, so the gotchas matter for any team that supports older OS releases.

  • Accessibility roles dropped in older browsers: Chrome below 89, Firefox below 62, and Safari below 16 strip the role from any element with display: contents, so screen readers no longer announce list, button, or heading semantics. The CSSWG draft says this is incorrect, and modern browsers keep the role.
  • Replaced elements collapse to display: none: img, input, video, canvas, iframe, embed, and object treat display: contents as display: none per the CSS Display Module Level 3 spec, so the element vanishes entirely. Use a non-replaced wrapper instead when you need this behavior.
  • Tables lose their table role: Setting display: contents on table, thead, tbody, or tr breaks the table accessibility role on every browser before the engine fixes landed. Screen readers stop announcing the rows and columns, even when sighted users still see them. Avoid the property on table elements.
  • Buttons lose click-target semantics: Older WebKit and Chromium versions remove the button role from a button styled with display: contents, so keyboard navigation skips it. Pair the property with role="button" and tabindex="0" as a defensive fallback when you must support legacy iOS Safari.
  • fieldset and legend layout quirks: Several browsers ignore display: contents on fieldset entirely and continue to render the box, because the form rendering pipeline is hard-coded around it. Wrap the fieldset content in a different element if you need the children to participate in a grid.
  • No effect on the box-generation cascade: The element with display: contents leaves no box, so margin, padding, border, background, transform, opacity, and outline are all ignored. Move those declarations to either the parent or to the children.

In my experience, the loudest production bug from display: contents shows up on iOS Safari 16 builds where a navigation list rendered fine visually but VoiceOver announced "blank" instead of the list, because the older WebKit accessibility tree had not yet caught up. The cheapest fix is a feature query that disables display: contents on browsers that fail an in-page accessibility-role probe.

...

How do you check if a browser supports CSS display: contents?

Detect display: contents by reflecting it through the CSSOM and the CSS.supports() API. Both checks should agree before you apply the property to a semantic wrapper.

  • Open the DevTools console: Press F12 or right-click the page and choose Inspect, then switch to the Console tab.
  • Reflect the value through the CSSOM: Create a div in JavaScript, set element.style.display = 'contents', and read the value back. If the browser supports the value, the read-back is the literal string "contents"; otherwise it is empty.
  • Confirm with CSS.supports(): Call CSS.supports('display', 'contents'). The method returns true on Chrome 65+, Edge 79+, Firefox 37+, Safari 11.1+, Opera 52+, and Samsung Internet 9.2+, and false on Internet Explorer and unsupported builds.
  • Gate the rule with @supports: Wrap any display: contents declaration in @supports (display: contents) so older browsers fall back to the wrapper's default block or inline box without breaking the layout.
  • Add an accessibility probe for older engines: The CSSOM check returns true on Chrome 65 and Safari 11.1, but the role-stripping bug existed on those versions. Combine the support check with a User-Agent or version sniff if you must keep semantics safe on older builds.

Paste this snippet into the DevTools console of any browser to confirm display: contents support and verify both the CSSOM and CSS.supports() agree.

// Paste this into the DevTools console to confirm display: contents support.
const probe = document.createElement('div');
probe.style.display = 'contents';
const reflected = probe.style.display === 'contents';
console.log('reflected style:', reflected ? 'supported' : 'not supported');

// Confirm CSS.supports() agrees, since the CSSOM check is the authoritative one.
const cssSupports = CSS.supports('display', 'contents');
console.log('CSS.supports check:', cssSupports ? 'supported' : 'not supported');

// Final verdict combines both checks.
console.log('display: contents available:', reflected && cssSupports);

Citations

All CSS display: contents version numbers, accessibility notes, and platform behavior in this guide come from these primary sources:

Author

Prince Dewani is a Community Contributor at TestMu AI, where he manages content strategies around software testing, QA, and test automation. He is certified in Selenium, Cypress, Playwright, Appium, Automation Testing, and KaneAI. Prince has also presented academic research at the international conference PBCON-01. He further specializes in on-page SEO, bridging marketing with core testing technologies. On LinkedIn, he is followed by 4,300+ QA engineers, developers, DevOps experts, tech leaders, and AI-focused practitioners in the global testing community.

Open in ChatGPT Icon

Open in ChatGPT

Open in Claude Icon

Open in Claude

Open in Perplexity Icon

Open in Perplexity

Open in Grok Icon

Open in Grok

Open in Gemini AI Icon

Open in Gemini AI

Copied to Clipboard!
...

3000+ Browsers. One Platform.

See exactly how your site performs everywhere.

Try it free
...

Write Tests in Plain English with KaneAI

Create, debug, and evolve tests using natural language.

Try for free

Frequently asked questions

Did you find this page helpful?

More Related Hubs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests