While learning web components, I came across a peculiar case of CSS style "leaking" to the DOM apparently as a text node while it seems to work still. See in the provided image as pointed by the yellow arrow on how the CSS text shows up in the DOM as a text node. This can be tested by altering the CSS selector between *
(leaks) and div
(does not leak).
How could this be explained? See code and image and if you want to try out quickly, there's a pen at https://codepen.io/veksi/pen/WNvMOYg where you can switch the selector (tested with Firefox and Chrome).
<this-test>
<div>
<p>Some test text in div.</p>
<p>Some more some text in div.</p>
<p>And even more some text in div.</p>
</div>
<section>
<p>Some test text in section.</p>
<p>Some more some text in section.</p>
<p>And even more some text in section.</p>
</section>
</this-test>
const template = document.createElement('template');
template.innerHTML = `
<style>
/* Why does changing the following selector to
this-test > *
i.e. to the asterisk to match all elements, "leak" out while otherwise seem to work? */
this-test > div {
display: flex;
flex-direction: column;
color: hotpink;
}
p {
background: #abcabc;
padding: 1rem;
border: 0;
font-size: 1.5rem;
}
</style>
`;
class ThisTest extends HTMLElement {
constructor() {
super();
//Note that shadow root is not used.
this.appendChild(template.content.cloneNode(true));
}
}
window.customElements.define('this-test', ThisTest);
Not related to Custom Elements/Web Components
All DOM elements have a display:
setting
By default <title> , <script> and <style> tags have display:none
When you use * {display:block}
(or any setting)
the contents of those normally hidden elements are now displayed in the page
It is a fun way to display contents of inline STYLE and SCRIPT tags:
<title desc=" Title of this HTML document">Hello DOM World!</title>
<script desc=" Logs text to the DEV console">console.log("Hello from SCRIPT")</script>
<style>
*{
display:block;
font-size:9px;
color:red;
}
title,
script{
font-size:2em;
color:blue;
}
*:hover:after{
display:inline;
content:attr(desc);
color:green;
}
</style>
The first red style block is what SO injects in the snippet