Is there the HTML which is being ignored by CSS?

Viewed 85

Assume that in below HTML, the element with class ChildBar could be or could not be.

<div class="Parent">
    <div class="ChildFoo"></div>
    <div class="ChildBar"></div> <!-- Could not be -->
    <div class="ChildBaz"></div>
</div>

Also, assume that ChildBaz must retire from ChildFoo by 4px but from ChildBar - by 6px. In CSS, it will be:

.ChildFoo + .ChildBaz {
  margin-top: 4px;
}

.ChildBar + .ChildBaz {
  margin-top: 6px;
}

Now, I want to mount by JavaScript the element ChildBar to correct position, herewith:

  1. The changing of the markup around the ChildBar must not brake the JavaScript behaviour. It means the methods like Element.after() referes to sibling elements could not be used.
  2. I need the mounting, not displaying from the hidden state.
  3. The above styles must not be broken.

In the case of below markup, replaceWith solution would be easy.

<div class="Parent">
    <div class="ChildFoo"></div>
    <div id="ChildBarMountingPoint"></div>
    <div class="ChildBaz"></div>
</div>

Hoewever, the element with ID ChildBarMountingPoint brakes the styles. Is there some magic element which is being ignored by CSS thus .ChildFoo + ChildBaz is being correctly appied? (If no, the solutions branch with replaceWith is a dead end and I must find the other solutions branch).

1 Answers

Is there a "magic" element that doesn't exist for the purpose of CSS selectors - No. But only elements are matched by selectors, and there are other node types. Maybe you could use one of those.

For example, one possibility is to use a comment. Assuming that you know that the two/three elements will be in a known parent whose class is .Parent you could do:

document.querySelector('#addChildBar').addEventListener('click', () => {
  
  Array.from(document.querySelector('.Parent').childNodes).find(n => {
    return n.nodeType === 8 && n.data === ' ChildBarMountingPoint '
  }).replaceWith(Object.assign(document.createElement('div'), {
    className: 'ChildBar' 
  }));
  
})
.ChildFoo + .ChildBaz {
  margin-top: 4px;
  color: red;
}

.ChildBar + .ChildBaz {
  margin-top: 6px;
  color: green;
}
<div class="Parent"> 
    <div class="ChildFoo">foo</div>
    <!-- ChildBarMountingPoint -->
    <div class="ChildBaz">baz</div>
</div>
<hr>
<button type="button" id="addChildBar">Add ChildBar</button>

Comment nodes are node type 8.

If you don't know the parent, then you'll need to walk the DOM node by node to find the correct comment node.

Related