2

I'm working with CSS' display:contents paired with element>elementselector. As for the definition, the display:contents property:

Makes the container disappear, making the child elements children of the element the next level up in the DOM

So I have this example code:

.wrapper {
  background-color: red;
}

.hidden {
  display: contents;
}

.wrapper > .child {
  background-color: yellow;
}
<div class='wrapper'>
  <div class='hidden'>
    <div class='child'>I'm a child</div>
    <div class='child'>I'm a child</div>
  </div>

  <div class='child'>I'm a child</div>
  <div class='child'>I'm a child</div>
</div>

I was expecting to have all the childrens with yellow background, because the element>element selector should target them all (they are all at the same level when the property display:contents comes into play).

Why is this not the case? Is the CSS unable to target children in this way?

Temani Afif
  • 211,628
  • 17
  • 234
  • 311
Omagerio
  • 476
  • 2
  • 10
  • 1
    CSS selector only consider DOM structure without the CSS applied to it. Same logic if you use `display:none` on an element (ex: https://jsfiddle.net/gca6bm9y/) so this is a logical and expected result – Temani Afif Apr 30 '19 at 13:41
  • Check here for an explanation: https://bitsofco.de/how-display-contents-works/ basically it doesn't take out the element, but instead _only_ shows the element's content (textnode, children). Also no, it doesn't apply to other CSS rules – elveti Apr 30 '19 at 13:46

2 Answers2

7

From the official specification:

contents

The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes and text runs as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced in the element tree by its contents (including both its source-document children and its pseudo-elements, such as ::before and ::after pseudo-elements, which are generated before/after the element’s children as normal).

Note: As only the box tree is affected, any semantics based on the document tree, such as selector-matching, event handling, and property inheritance, are not affected.

The bold part is the answer you are looking for.

Also note the sentence: must be treated as if it had been replaced in the element tree by its contents. So the element isn't really removed but to make it easier to explain, it's like the element is removed and replaced by its content.


PS: avoid the use www.w3schools.com as an official reference for accurate definition like this. They can be good to explain things in general but will fail to give precise definition.

Community
  • 1
  • 1
Temani Afif
  • 211,628
  • 17
  • 234
  • 311
  • I'd considered editing your answer to include a visualization, but just to play it safe I put it in a separate answer. Also, I'm back. – BoltClock Sep 02 '19 at 06:37
  • @BoltClock Ah, welcome back :) .. you missed some intresting questions that you might like : https://stackoverflow.com/q/56238082/8620333 / https://stackoverflow.com/q/55653761/8620333 / https://stackoverflow.com/q/56186202/8620333 – Temani Afif Sep 02 '19 at 09:01
1

Adding to Temani Afif's answer, here's a visualization of what the box subtree for this element looks like with display: contents on .hidden:

<div class='wrapper'>
  <div class='child'>I'm a child</div>
  <div class='child'>I'm a child</div>

  <div class='child'>I'm a child</div>
  <div class='child'>I'm a child</div>
</div>

Indeed, it's rendered as though .hidden itself wasn't there and its own children were instead children of .wrapper (and in turn siblings of .wrapper's own children). That's essentially what display: contents means.

BoltClock
  • 665,005
  • 155
  • 1,345
  • 1,328