javascripthtmlcssshadow-domcustom-element

Modifying custom elements' style in shadow root


I am attempting to modify the styles of two custom HTML elements, "output-screen" and "custom-calculator" using shadow DOM.

When I try to do so by attaching a shadow DOM as shown below, the styles are not applied. Any ideas what I'm doing wrong?

JS Fiddle

<custom-calculator id="calculator">
  <output-screen></output-screen>
</custom-calculator>

<script>
var o = Object.create(HTMLElement.prototype);
    var oElement = document.registerElement('output-screen', {
        prototype: o
    });

var c = Object.create(HTMLElement.prototype);
var cElement = document.registerElement('custom-calculator', {
  prototype: c
});

var calc = document.querySelector('#calculator')
calc.attachShadow({ mode: 'open' });
calc.shadowRoot;
calc.shadowRoot.innerHTML = `
<style>
output-screen{
display:inline-block;
background-color:orange;
width:50%;
height:100vh;
}
custom-calculator {
display:inline-block;
background-color:grey;
width:100%;
height:100vh;
vertical-align:top;
}
</style>
`;
</script>

Solution

  • In order to style the element that hosts the Shadow DOM, here <custom-calculator>, you must use de :host pseudo-class (instead of custom-calculator which is unknown inside the Shadow DOM).

    :host {
      display:inline-block;
      background-color:grey;
      width:100%;
      height:100vh;
      vertical-align:top;
    }
    

    Because the Shadow DOM will replace/recover the normal DOM tree (here <output-screen>), you'll have to use <slot> to insert/reveal it in the Shadow DOM.

    calc.shadowRoot.innerHTML = `
      <style>
        ...
      </style>
      <slot></slot>`
    

    Then, in order to style what is revealed by/in the <slot> element, you mus use the ::slotted() pseudo-element:

    ::slotted( output-screen ){
      display:inline-block;
      background-color:orange;
      width:50%;
      height:100vh;
    }
    

    Live example:

    var calc = document.querySelector('#calculator')
    calc.attachShadow({mode: 'open'});
    calc.shadowRoot.innerHTML = `
      <style>
        :host {
          display:inline-block;
          background-color:grey;
          width:100%;
          height:100vh;
          vertical-align:top;
        }
    
        ::slotted( output-screen ){
          display:inline-block;
          background-color:orange;
          width:50%;
          height:100vh;
        }
      </style>
      <slot></slot>`;
    <custom-calculator id="calculator">
      <output-screen></output-screen>
    </custom-calculator>