Web_Components family - CSS selector for Shadow Host

preface

In the previous section, we learned how to set styles for custom components. At that time, we set the styles of custom labels in the main DOM:

<style>
    my-card {
        display: block;
        margin: 20px;
        width: 200px;
        height: 200px;
        border: 3px solid #000;
    }
</style>
<my-card></my-card>

Although the purpose of style setting is realized, there is a disadvantage: the style of custom label is written dead and not flexible enough.

If you can control the style of user-defined labels inside the user-defined component, it will be relatively flexible, and it can also realize the component principle of "encapsulation and isolation". Today, let's learn how to control the style of user-defined labels inside the user-defined component.

Before starting the text, let's review the overall structure of Shadow DOM:

CSS selector for Shadow DOM

Today's focus is on recognizing several selectors related to Shadow DOM.

: host pseudo class selector

Select the Shadow host element that uses this part of CSS internally, which is actually a custom label element. The usage is as follows:

:host {
    display: block;
    margin: 20px;
    width: 200px;
    height: 200px;
    border: 3px solid #000;
}

Note: the host selector works only when used in the Shadow DOM.

For example:

In addition, you can use the form of: host sub selector to set the style for the sub elements of Shadow Host, such as:

: the compatibility of the host pseudo class selector is as follows:

: host() pseudo class function

: host() is used to get the Shadow Host of a given selector. For example, the following code:

<my-card class="my-card"></my-card>
<my-card></my-card>

<script>
    class MyCard extends HTMLElement {
        constructor () {
            super();
            this.shadow = this.attachShadow({mode: "open"});
            let styleEle = document.createElement("style");
            styleEle.textContent = `
                :host(.my-card){
                    display: block;
                    margin: 20px;
                    width: 200px;
                    height: 200px;
                    border: 3px solid #000;
                }
                :host .card-header{
                    border: 2px solid red;
                    padding:10px;
                    background-color: yellow;
                    font-size: 16px;
                    font-weight: bold;
                }
            `;
            this.shadow.appendChild(styleEle);


            let headerEle = document.createElement("div");
            headerEle.className = "card-header";
            headerEle.innerText = "My Card";
            this.shadow.appendChild(headerEle);
        }
    }

    window.customElements.define("my-card", MyCard);

</script>

: host (. My card) will only select the custom element with the class name of my card, and it can also be followed by a sub selector to select the sub elements under its own node.

It should be noted that the parameter of:: host() must be passed, otherwise the selector function will fail, such as:

: host() pseudo class functions are compatible as follows:

: host context() pseudo class function

Used to select custom elements within a specific ancestor. The ancestor element selector is passed in through parameters. For example, the following code:

<div id="container">
    <my-card></my-card>
</div>
<my-card></my-card>
<script>
    class MyCard extends HTMLElement {
        constructor () {
            super();
            this.shadow = this.attachShadow({mode: "open"});
            let styleEle = document.createElement("style");
            styleEle.textContent = `
                :host-context(#container){
                    display: block;
                    margin: 20px;
                    width: 200px;
                    height: 200px;
                    border: 3px solid #000;
                }
                :host .card-header{
                    border: 2px solid red;
                    padding:10px;
                    background-color: yellow;
                    font-size: 16px;
                    font-weight: bold;
                }
            `;
            this.shadow.appendChild(styleEle);


            let headerEle = document.createElement("div");
            headerEle.className = "card-header";
            headerEle.innerText = "My Card";
            this.shadow.appendChild(headerEle);
        }
    }

    window.customElements.define("my-card", MyCard);

</script>

: host context (#container) will only take effect for user-defined elements whose id is container. The effect is as follows:

Note: the parameters here are also required, otherwise the whole selector function will not take effect.

Its compatibility is as follows:

The necessity of coexistence of: host and: host()

After reading the above introduction, many people may have a doubt: host (. My card) {} can't be used directly: host My card {} instead?

The answer is no!!!, Because:: host My card essentially means to find My card (Shadow root): host (Shadow Host). The structure of Shadow DOM is contradictory.

summary

The above is about the CSS selector of Shadow Host. To summarize:

  • : host has the largest range and matches all user-defined element instances;
  • : host() selects only custom elements that contain a specific selector;
  • : host context() selects a custom element that has a specific selector parent element.

~End of this article, thank you for reading!

Added by phaseonemedia on Wed, 16 Feb 2022 14:40:14 +0200