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.
If I then add the display property with a value of contents to the outer div, we now get this:
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.
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.
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.