What’s so great about display: contents?

Nesting inside a grid

In October Chris Coyier wrote a CSS Tricks article entitled Will we be flattening our HTML for CSS Grids? He worried that by using grid would lead people to flatten out their HTML — by which he meant people would avoid nesting elements inside other elements.

There are plenty of HTML elements that need to be nested to have valid HTML — list items, form elements, etc. What if we want these nested elements to be grid items?

Just like with flexbox, only direct children of a CSS grid become grid items. Anything that is further-nested can’t be placed using grid-positioning.

Subgrids are one solution to this problem, but are unlikely to be implemented in any browser until late 2017. There is another property value that fulfills a similar function and that is already implemented in Firefox — display: contents.

The Level 3 Display Module spec explains

The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced with its children and pseudo-elements in the document tree.

Let’s take an unordered list as an example. If we have a 12 column grid and place a <ul> inside of it, the unordered list will become a grid item and will, along with its entire contents, span one column and one row. We can apply the new grid positioning properties to the whole entire unordered list to move where it is placed on our grid, or to make it span more columns or rows. However, we can’t use any grid properties on the list items themselves, because they are not direct children of the grid. We can’t place an individual li in a particular row or column or grid area. Because nesting is pretty common in HTML, this could be a bit of a drawback.

However, once we set the <ul> to display: contents each <li>will become grid items. We will no longer be able to use grid-positioning properties on the <ul>element, but will be able to use them on the <li>. By using display: contentson the parent element, its children have become grid items.

This simple example can be found on CodePen. Try deleting display: contents and see what happens. [Reminder: This property is currently only implemented in Firefox].

By using this new property value, we can use our grid columns and rows to position items, regardless of whether they are nested or not.

This new value can also be used in conjunction with flexbox to make nested items flex items.