7
votes

Is there a way to inherit :host element css styles into shadow DOM? The reason is if we start developing web components, each web component style must be consistent on a page.

The page can have global css, and this global css styles can be inherited to shadow DOM. There was ::shadow and /deep/, but it's deprecated now.

Or, is this against pattern? If so, why?

I found this Q/A, but seems outdated for me. Can Shadow DOM elements inherit CSS?

http://plnkr.co/edit/qNSlM0?p=preview

const el = document.querySelector('my-element');
el.attachShadow({mode: 'open'}).innerHTML = `
  <!-- SEE THIS 'red' is not red -->
  <p class="red">This is defined in Shadow DOM. I want this red with class="red"</p>
  <slot></slot>
`;
  .red {
    padding: 10px;
    background: red;
    font-size: 25px;
    text-transform: uppercase;
    color: white;
  }
<!DOCTYPE html>
<html>

<head>
  <!-- web components polyfills -->
  <script src="//unpkg.com/@webcomponents/custom-elements"></script>
  <script src="//unpkg.com/@webcomponents/webcomponentsjs"></script>
  <script src="//unpkg.com/@webcomponents/shadydom"></script>
  <script src="//unpkg.com/@webcomponents/[email protected]/apply-shim.min.js"></script>
</head>

<body>

<div>
  <p class="red">I'm outside the element (big/white)</p>
  <my-element>
    <p class="red">Light DOM content is also affected.</p>
  </my-element>
  <p class="red">I'm outside the element (big/white)</p>
</div>

</body>

</html>
2
Have you considered using CSS Variables and mixins instead? If you expose them, they will allow you to overwrite or configure the componentsJose A

2 Answers

2
votes

As supersharp pointed out it's very simple but not obvious from the examples you can find on the internet. Take this base class as an example. Alternatively, you could make two different ones (e.g. Component and ShadowComponent). There is also the option to use adoptedStyleSheets or the ::part selector.

class HtmlComponent extends HTMLElement {
    static ModeShadowRoot = 0;
    static ModeRoot = 1;
    static styleSheets = [];
    static mode = HtmlComponent.ModeShadowRoot;

    #root = null;

    constructor() {
        super();
        if (this.constructor.mode === HtmlComponent.ModeShadowRoot) {
            const shadowRoot = this.attachShadow({ mode: 'closed' });
            shadowRoot.adoptedStyleSheets = this.constructor.styleSheets;
            this.#root = shadowRoot;
        } else {
            this.#root = this;
        }
    }

    get root() {
        return this.#root;
    }

    init() {
        this.root.innerHTML = this.render();
    }

    render() {
        return '';
    }
}


class Test extends HtmlComponent {
    static mode = HtmlComponent.ModeRoot;

    constructor() {
        super();
        super.init();
    }

    render() {
        return `
            <div>
                <x-nested-component></x-nested-component>
            </div>
        `;
    }
}
1
votes

One of the features of Shadow DOM is to isolate CSS styles.

So if you want your Custom Elements to inherit styles from the main page, don't use Shadow DOM. It's not mandatory.