Correct way to apply global styles into Shadow DOM
There's no real drawback with solution 3:
Whether you apply a CSS style to n elements in a main document, or to 1 element in n Shadow DOM, the style will be duplicated to the whole n elements anyways.
If you import a document n times in n Shadow DOM, il will be actually be loaded only one time and reused through the browser cache.
After that, it will depend on the browser implementation of Shadow DOM and CSS styles, and you should see a performance degradation only the thousands of Shadow DOM.
2019 update for Chrome 73+ and Opera 60+
Now you can directly instanciate a CSSStyleSheet
object and assign it to different Shadow DOMs.
This way the HTML won't be duplicated.
var css = new CSSStyleSheet()
css.replaceSync( "@import url( main.css )" )
host.shadowRoot.adoptedStyleSheets = [css]
host2.shadowRoot.adoptedStyleSheets = [css]
You can also apply it to the global document:
document.adoptedStyleSheets = [css]
The other advantage is that an update on the stylesheet will be applied to all Shadow DOMs (and document) that adopted it.
css.replaceSync( '.color { color: red }' )
Global CSS effect on Shadow element. Why?
It's the normal behavior of CSS styles. The elements inserted in the Shadow DOM with <content>
(in your example: <span class=name>...</span>
) are actually part of the normal DOM, and therefore are affected by the global CSS styles.
If you don't dont want it, you should try another technique, like copying the light DOM elements into the Shadow DOM instead of using <content>
.
Also, you should use Custom Elements v1 (and customElements.define()
) and Shadow DOM v1 (and <slot>
) instead of Custom Elements v0 (registerElement()
) and Shadow DOM v0 (<content>
) which are deprecated.
With Shadow DOM v1, you can use ::slotted()
inside the Shadow DOM to select and style insterted elements.
You can then overload the CSS rule in the Shadow DOM <style>
with the !important
modifier:
line 21:
<style>
::slotted( span ) {
text-decoration: underline!important
}
</style>
Below is the complete snippet:
//CREATE CUSTOM ELEMENTclass MyContact extends HTMLElement { constructor() { super() //retrieve template var tpl = document.querySelector('#contact-form-tpl'); var tpl_ct = document.importNode(tpl.content, true);
//this <=> my-contact element -> create shadow var shadowRoot = this.attachShadow( {mode:'open'}) //createShadowRoot();
//show template in shadow DOM shadowRoot.appendChild(tpl_ct); }}
//REGISTER CUSTOM ELEMENTcustomElements.define("my-contact", MyContact);
span { text-decoration: line-through}
<script src="https://cdnjs.cloudflare.com/ajax/libs/document-register-element/1.11.0/document-register-element.js"></script><span>HELLO</span><!--line through by css at LINE 6: OK--><my-contact> <h1 slot=header>Contact X</h1> <span slot=name>this is my name</span> <span slot=phone>this is my phone</span></my-contact>
<template id="contact-form-tpl"> <style> span ::slotted( span ), span { text-decoration:underline!important } </style> <fieldset> <legend> <slot name=header></slot> <div> Name: <span><slot name="name"></slot></span> </div> <div> Phone: <slot name="phone"><span></span></slot> </div> <span>TEST</span><!-- only apply css at line 21: OK--> </legend> </fieldset></template>
Related Topics
How to Add a List of Images to the Document from an Array of Urls
JavaScript Set CSS :After Styles
Make the on Scroll Growing <Path> to Dashed Line
Difference Between Jquery .Hide() and .Css("Display", "None")
Getting Last-Child of a Div in IE8
How to Convert Rgba to Hex Color Code Using JavaScript
How to Pass Styles to Child Component and Use It as Scoped Style in Vue
Jquery Animate Top (From Bottom to Top)
Download Attribute Not Working in Firefox
JavaScript Click Event Listener on Multiple Elements and Get Target Id
Css3 Keyframe Animations: End and Stay on the Last Frame
Export SASS/Scss Variables to JavaScript Without Exporting Them to CSS
Jquery UI Switchclass() Method Is Not Working Properly
Make View 80% Width of Parent in React Native
Image Slider: Maintaining Equal Height for All Images While Keeping Slider Responsive