CSS display: contents: Grid Layout Without Wrappers
Grid layout without extra wrapper elements
Grid and flex layouts only apply to direct children. When markup wraps items in extra elements, the layout breaks. display: contents removes a wrapper from the layout tree so its children behave as if the wrapper was never there.
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;}.wrapper { display: grid; grid-template-columns: subgrid; grid-column: span 3; }/* no native way to flatten — restructure HTML or repeat grid on wrapper */ .wrapper { display: contents;}/* wrapper disappears from layout; children join parent grid */ display contents Browser Support
This feature is well established and works across many devices and browser versions. It has been available across browsers since 2020.
Safe to use without fallbacks.
No HTML restructuring
Keep semantic or component wrapper elements in the markup. The grid sees through them automatically.
Web components friendly
Custom elements and framework wrappers can opt into parent layouts without the host element creating a new stacking or formatting context.
Works with any layout
Transparent to grid, flex, and multi-column containers. Children participate as if the wrapper were absent.
How it works
Grid and flexbox layouts only apply to direct children of the container. When a wrapper element sits between the container and the actual items, it creates a new box in the layout tree and the children fall outside the grid tracks. The old fix was to flatten the HTML or avoid the wrapper entirely.
display: contents removes an element's principal box from the layout. The element still exists in the DOM and still holds its children, but it contributes no box to the visual formatting model. Its children are treated as direct children of the element's parent, so they slot into grid and flex layouts as expected.
One gotcha: display: contents strips box-model properties from the element itself. Backgrounds, borders, padding, and margins on the wrapper are ignored. Only apply it to elements you genuinely want to be invisible to layout. Also avoid applying it to interactive elements like <button> or <a> where it can strip the accessible role in some browsers.