Why does my Web Component CSS not show? I am not using shadowDOM
If you are creating a component that does NOT use ShadowDOM that you may still need to add your CSS into a shadowRoot. If someone else places your component into their shadowDOM, then you must add your CSS to their shadowRoot. You can do this with the following code:
const myStyle = document.createElement('style');myStyle.setAttribute('component', 'my-el');myStyle.textContent = ` button { padding: 8px 20px;}.happy-btn { background-color: pink;}
.sad-btn { background-color: #007; color: white;}`;
function addCss(el, selector, styleEl) { // Check to see if we have been placed into a shadow root. // If we have then add our CSS into that shadow root. let doc; try { doc = el.getRootNode(); if (doc === document) { doc = document.head; } } catch(_ex) { doc = document.head; } // Shadow DOM isn't supported.
if (!doc.querySelector(selector)) { doc.appendChild(styleEl.cloneNode(true)); }}
class MyEl extends HTMLElement { constructor() { super(); addCss(this, 'style[component="my-el"]', myStyle); } connectedCallback() { this.innerHTML = `<div class="spaced"><button class="happy-btn">I'm Happy</button></div> <div class="spaced"><button class="sad-btn">I'm Sad</button></div>`; }}customElements.define('my-el', MyEl);
class TheirEl extends HTMLElement { constructor() { super(); this.attachShadow({mode:'open'}); this.shadowRoot.innerHTML = `<hr/><my-el></my-el><hr/><my-el></my-el><hr/>`; }}customElements.define('their-el', TheirEl);
<their-el></their-el>
HTML web component does not use shadow DOM style
While this question already has an accepted answer, moving a slot's children to the shadowRoot isn't desirable for most use cases.
What you probably want to do is to use the ::slotted()
selector.
Just bear in mind that styles applied to a slot's children through the ::slotted()
selector only act as "default" styles and can still be overridden by using styles in light DOM.
For example, check this edited version of your snippet:
As you can see, this time my-el
tries to apply both a color and a text-decoration style to anchor (<a>
) children in any of it's slots.
However, in light dom, we have a a.special
selector that overrides the color, so the <a class="special">
will be red, not green
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
::slotted(a) {
color: green;
text-decoration: none;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a.special {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a class="special" href="example.com">Item2</a>
</my-el>
Outside stylesheet css not work in the shadow dom (HTML Web Component)
Here's some basic about 'Shadow Dom'!
My problem above was didn't know inside of shadow dom, element can't see any code outside of the container. the best soultion i found so far was code below:
Simplely create a link tag to the style sheet just like what we did in nomal html.
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'style.css');
shadow.appendChild(linkElem);
shadow dom style not showing
If you define a SVG element with createElement
, you should set the specific SVG namespace which is http://www.w3.org/2000/svg
.
You must then use createElementNS()
method:
this.svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
Slots does not work on a html web component without shadow dom
Yes, <slot>
only works in shadowDOM
Slotted content is reflected lightDOM content
See: ::slotted CSS selector for nested children in shadowDOM slot
A Web Component without shadowDOM only has innerHTML
If you do this.innerHTML=
on such a Web Component it replaces the innerHTML
, just like on any other HTML tag
with shadowDOM:
<hello-world>
<b slot="none">Mighty</b>
<span slot="title">Web Components</span>
Hello!
</hello-world>
<script>
customElements.define("hello-world", class extends HTMLElement {
constructor() {
super()
.attachShadow({mode:"open"})
.innerHTML = `<div><slot></slot><slot name="title">Foo Bar</slot></div>`;
this.onclick = (evt) => this.querySelector('b').slot = "title";
}
});
</script>
CSS is not fully applying on a shadow DOM using slot
Default value for CCS property color
is inherit.
Default style for CSS property background-color
is transparent (won't inherit from its parent element).
Default custom element display
property is inline (= phrasing content) and therefore won't settle background properties to its children.
In your code, the "Test" text is in a <p>
element, that won't inherit from the :host
background color, but will be transparent and therefore will display the background color of the main page, which is white
.
See the live example below for a complete use case.
const template = document.createElement('template')template.innerHTML = ` <style> :host { background-color: var(--my-bg); color: var(--my-text); } </style> <slot></slot> <hr> Text in Shadow DOM root <p>Text in Paragraph in Shadow DOM <span>and child Span</span></p> <span>Text in Span in Shadow DOM <p>and child Paragraph</p></span>`class MyElement extends HTMLElement { constructor() { super() this.attachShadow({mode: 'open'}) .appendChild(template.content.cloneNode(true)) }}window.customElements.define('my-element', MyElement)
body { background-color: lightblue;}
my-element { --my-bg: green; --my-text: red;}
<my-element myStyling> Text in Light DOM root <p>Text in Paragraph in Light DOM <span>and Child Span</span></p> <span>Text in Span in Light DOM <p>and child Paragraph</p></span></my-element>
CSS property 'cursor' not working with :host selector
Runs fine:
customElements.define("my-element", class extends HTMLElement {
connectedCallback() { // so attributes can be queried
this
.attachShadow({mode:"open"})
.innerHTML = `<style>
:host {
display: inline-block;
}
:host([disabled]) {
cursor: not-allowed !important;
background: pink !important;
color: grey !important;
}
</style>
<h1><my-element
${this.hasAttribute("disabled")?"disabled":""}></h1>`;
}
})
<style>
my-element{
cursor: pointer;
background: lightgreen;
color: green;
}
</style>
<my-element></my-element>
<my-element disabled></my-element>
Related Topics
How Is The Screen Size Measured for Media Queries
Javafx 8 - How to Change The Color of The Prompt Text of a Not Editable Combobox via CSS
Loops Make Less to Run Out of Memory. (Structure Optimization)
Overlaping Effect on Cards with Pure CSS
Change Height-Top of Item When Hover
Skew The Shadow, Not The Content
How to Give Internet Explorer Different CSS Lines
Convert Less Nested CSS to Standard CSS
Overlap Notification Badge on Glyph in Bootstrap 3
Flexbox Column Align Self to Bottom
Understanding Margin-Collpasing
How to Scale Svg Path to Fit The Window Size
Responsive Irregular Background Shape with CSS
Vuetify Without Vue-Cli Sass/Scss Conflict
How to Achieve This Visual Using CSS