Web_Components family - CSS selector for Shadow Host

Posted by nubby on Wed, 16 Feb 2022 13:22:31 +0100

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!

~

Learn interesting knowledge, make interesting friends and shape interesting souls!

Hello, I'm Programming samadhi Hermit Wang, my official account is " Programming samadhi "Welcome to pay attention and hope you can give us more advice!