Vanishing boxes with display contents

In the CSS Display Module Level 3 is a new value for the display property – display: contents. The value has been implemented in Firefox and here is a quick explanation of what it does, and why it might be useful if it gets wider browser support.

The specification says

“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.“

This means you can have an HTML element in your document, add display:contents to a selector for that element and it will act as if it does not exist and it’s child elements take up it’s place in the document tree.

This is far easier to understand with an example. You will need to use Firefox.

I have two div elements, an outer div with a class of content and an inner div with a class of inner. With some CSS added to create backgrounds and borders I end up with this.

simple example of display contents

If I then add the display property with a value of contents to the outer div, we now get this:

after applying display contents

The outer div has vanished, we can’t see the background, border, and even the width applied to that element has gone and the inner is taking up full width of the viewport. That’s how display: contents works. Here is the CodePen, use Firefox to have a play around. In non-supporting browsers display:contents will be ignored.

It is worth noting that it is only properties to do with box-generation and layout that do not inherit. You can see this by setting a font-size on the outer div, the child will still take on that size.

See the Pen display: contents by rachelandrew (@rachelandrew) on CodePen.

Using display: contents to make the children of a flex item behave like flex items

Where might this be useful? If you are using flexbox then you will know that only direct children of the flex container become flex items. Children of that flex item are not laid out using the rules applied to the parent.

You can see this with a simple example. Here I have a wrapper div with box1, box2 and box3 classes applied to divs nested directly inside. These items are flex items and I can lay them out with flexbox. However box4 and box5 are children of box2 and so even through I have applied rules to box5, it ignores them as it does not have a parent set to display: flex;

I’ve added a bright background and border to box2 to help us see what happens here.

Flex items before using display contents

If I add display: contents to box2 in Firefox you can see that box2 has gone visually – we cannot see the orange border and background. Not only that but it seems as if it has completely disappeared from the document tree. The children of box2 are now behaving like flex items and the rules I applied to box5 are working.

Flex items after using display contents

Here it is as a CodePen.

See the Pen display: contents and flexbox by rachelandrew (@rachelandrew) on CodePen.

A note of thanks to Jake Archibald for getting me started with this with his example.

This value becomes useful if you want to add some element because it makes sense in terms of document semantics, but doesn’t in terms of display. Perhaps you have some content that makes sense marked up as an article, that article is then a flex item in your layout BUT the elements you really would like to be flex items are nested inside that article. Rather than flattening your markup and remove the article element to enable these inner elements to be part of the flex layout, you could remove the boxes generated by article using display: contents. You then get the best of both worlds, semantic markup plus the visual display your design requires. That sounds good to me.

Published on the

The CSS Layout Online Workshop

If you are ever baffled by floats, puzzled by collapsing margins or want to understand what is happening under the hood of a framework, this course is for you.

Comments

Jeremy Keith on the 30 Jan 2016 at 16:35:51:

So, could this potentially be a solution to the sub-grids issue?

If I understand the problem correctly, it’s that the grid styles only get applied to siblings (much like the flexbox example). With display: contents, could the “gridiness” be bubbled down into children?

To use the example in Eric’s blog post*, if display:contents were applied to the list item elements, could you then apply display:grid to the labels and form fields?

* http://meyerweb.com/eric/thoughts/2016/01/15/subgrids-considered-essential/

Rachel Andrew on the 30 Jan 2016 at 18:30:29:

It’s kind of a hacky solution for trivial cases and the reason I was looking into it. Having looked into it I thought I’d write it up. I’ve got grid cases too, and I’ll write those up next.

Keith Wyland on the 31 Jan 2016 at 18:18:07:

[i think] This would solve EXACTLY the problem I was having with flexbox that I hacked around with floats+flexbox here: http://codepen.io/keithwyland/details/rxpOgZ/#0

That would be awesome! Do we know what support is like for this?

Joe Zimmerman on the 03 Feb 2016 at 15:16:43:

Keith, according to the article, it seems like only recent versions of Firefox have support for this at the moment.

Dan Farrow on the 03 Nov 2016 at 21:39:57:

Instantly pulverise any website with `* { display: contents !important }`

Yay!

Leave a reply