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 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.
8 Comments
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/
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.
[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?
Keith, according to the article, it seems like only recent versions of Firefox have support for this at the moment.
Instantly pulverise any website with `* { display: contents !important }`
Yay!
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-…
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.
Yesterday, @paul_kinlan @brendaneich @rachelandrew @pfrazee @potch @patrickkettner gave a state of @chrome @microsoftedge @firefox @beakerbrowser @brave. Watch it here. buff.ly/2i8SAdD