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.

8 Comments

Jeremy Keith January 30, 2016 Reply

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 January 30, 2016 Reply

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 January 31, 2016 Reply

[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 February 3, 2016 Reply

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

Dan Farrow November 3, 2016 Reply

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

Yay!

SelenIT November 15, 2017 Reply

WebKit has just shipped display:contents (rachelandrew.co.uk/archives/2016/…) by default: trac.webkit.org/changeset/2248…
This makes it the 2nd SHIPPED implementation (after Gecko’s). Chrome’s one is also almost ready.

Only MS is left behind (again). Let’s change that! wpdev.uservoice.com/forums/257854-…

@rem November 15, 2017 Reply

There really isn’t a “dive in and use blindly” version of css grid (**for me**). There’s a few amazing resources (ht @rachelandrew), but there ain’t no groking by scanning and going.

Leave a Reply