Refer to my previous answer for some helpful tips: Utilizing CSS selectors like :first-child within shadow DOM
Your elements will remain hidden in lightDOM!
Any global styles you apply will be reflected in the shadowDOM.
customElements.define('my-custom-element', class extends HTMLElement {
constructor(){
super()
.attachShadow({mode: 'open'})
.innerHTML = `<slot></slot><style>:host { color: red; }</style>`;
}
});
<div>
<my-custom-element>first</my-custom-element>
<my-custom-element>... more elements</my-custom-element>
<my-custom-element>last</my-custom-element>
</div>
<style>
div my-custom-element:last-child {
padding: .5em;
background: green;
}
</style>
Additional Notes:
super()
returns 'this' (the element itself), allowing you to chain methods on it
attachShadow
returns this.shadowRoot
, enabling you to chain methods on it
The :host-context
selector may not be supported by FireFox and Safari
see: :host-context not working as expected in Lit-Element web component
Regarding the comment:
This may be the correct solution, but it can be disappointing. The purpose of the shadow DOM was supposed to be self-contained, so having to use global styles to style elements within the shadow DOM doesn't seem ideal. It's no surprise people turn to frameworks like React and Vue when web standards are lacking.
Consider this perspective: if your my-custom-element
were <p>
elements, how would a <p>
know it is inside the last-child
... only by referencing its parent container.
No wonder people turn to frameworks like React and Vue when web standards are lacking.
All Frameworks operate similarly, wrapping content in containers
(be it in regular DOM, shadowDOM, virtual DOM)
A more accurate statement: Frameworks frame your content in containers.. always
The Native W3C standard Custom Element API grants 100% control over utilizing a container or not.
Yes, this means you must do some scripting before enjoying the benefits.
You have complete freedom in crafting components as you wish.
React adds 48 KB (GZipped) to your download, along with build processes and compatibility issues with other frameworks. Additionally, it no longer conforms to the ES standard.
Crafting an additional Custom Element takes about 15 minutes and approximately 200 bytes