Styling a child of a shadow root in Shadow DOM

Yuval A. picture Yuval A. · Mar 6, 2017 · Viewed 7.9k times · Source

I'm trying to style a child element of a shadow DOM root.
This defines a custom element called element-el, which have a span class-named 'x' with the letter x in it, which I want, for the state of the matter, to be red.

class El extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({mode:'open'});
        shadow.innerHTML = '<span class="x">X</span>';
    }
}
customElements.define ('element-el',El);

I've tried those CSS styles:

element-el::slotted(.x) {
  color:red;
}
element-el::host .x {
  color:red;
}
element-el:host .x {
  color:red;
}
element-el::shadow .x {
  color:red;
}
element-el /deep/ .x {
  color: red;
}
element-el::content .x {
  color:red;
}

The X does not become red. I'm using Chrome 56, which is supposed to support this...

I want to style it without putting a style element inside the shadow DOM.
Here is a codepen: http://codepen.io/anon/pen/OpRLVG?editors=1111

EDIT:
This article suggests that it is possible to style shadow children from an external CSS file -- are they simply wrong?

Answer

Romulo picture Romulo · Mar 6, 2017

Apparently the problem is the fact that you are trying to use the global CSS to style the shadow tree elements.

You can use the :host pseudo selector, however in order to do so you will have to place the style inside the shadow tree content.

Make the following changes in your javascript:

class El extends HTMLElement {

    constructor() {
        super();
        var shadow = this.attachShadow({mode:'open'});
        var innerHTML = '';
        innerHTML += '<style>';
        innerHTML += ':host(element-el.red) span {color: red}';
        innerHTML += ':host(element-el.green) span {color: green}';
        innerHTML += ':host(element-el.blue) span {color: blue}';
        innerHTML += '</style>';      
        innerHTML += '<span class="x">X</span>';      
        shadow.innerHTML = innerHTML;
    }

}

customElements.define ('element-el',El);

Check a functional example in your updated codepen.