0

After my testing, it is effective to write css directly using nesting, but in WebComponent, it is invalid after nesting with :host selector. The following is the demo code, My Chrome version number is 117

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="/index.js" type="module"></script>
  </head>
  <body>
    <template class="template_testCom">
      <style>
        :host {
          width: 200px;
          height: 50px;
          display: flex;
          justify-content: center;
          align-items: center;
          font-weight: 700;
          background-color: #c00;

          & .container {
            display: flex;
            width: 100%;
            height: 70%;
            background-color: #fcf;
            & .text {
              color: #fff;
            }
          }
        }
      </style>

      <div class="container">
        <span class="text">textContent</span>
      </div>
    </template>
  </body>
</html>

index.js

import TestCom from "/TestCom.js";
window.customElements.define("test-com", TestCom);
const com_testCom = new TestCom();
document.body.append(com_testCom);

TestCom.js

class TestCom extends HTMLElement {
  constructor() {
    super();
    this.#init();
  }
  #init() {
    const shadowRoot = this.attachShadow({ mode: "open" });
    const ele_templateTestCom = document.querySelector(".template_testCom");
    const content = ele_templateTestCom.content.cloneNode(true);
    shadowRoot.appendChild(content);
  }
}

export default TestCom;

enter image description here

The following is a test, when non-WebComponent uses CSS nesting, the styles within CSS nesting are in normal use.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .noWebComponent {
        width: 200px;
        height: 50px;
        display: flex;
        justify-content: center;
        align-items: center;
        font-weight: 700;
        background-color: #c00;

        & .container {
          display: flex;
          width: 100%;
          height: 70%;
          background-color: #fcf;
          & .text {
            color: #fff;
          }
        }
      }
    </style>
  </head>
  <body>
    <div class="noWebComponent">
      <div class="container">
        <span class="text">textContent</span>
      </div>
    </div>
  </body>
</html>

enter image description here

1
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. Commented Oct 14, 2023 at 13:57

1 Answer 1

0

Nested CSS can not cross shadow boundaries.

:host (yellow) references the Web Component itself, not the shadowDOM inside

.

So your non-Web-Component code that works for you (green),
should be copied 1:1 to the shadowDOM to apply your nested CSS on a DOM node inside shadowDOM (blue)

<style id="STYLE">
  .wrapper {
    width: 200px; height: 50px;
    display: flex; justify-content: center; align-items: center;
    font-weight: bold;
    background-color: brown;
    & .container {
      background-color: grey;
      & .text {
        color: gold;
      }
    }
  }
</style>

<b>DOM, no shadowRoot:</b>
<div class="wrapper" id="WRAPPER">
  <div class="container">
    <span class="text">textContent</span>
  </div>
</div>

<script>
  customElements.define("text-component", class extends HTMLElement {
    constructor() {
      super()
        .attachShadow({mode: "open"})
        .innerHTML = `<style>${STYLE.innerHTML}</style>` + WRAPPER.outerHTML;
    }
  });
</script>
<b>Web Component:</b>
<text-component></text-component>

Note: you can do it with :host and without the .wrapper DIV. But you can not use nested styles accross shadowRoot boundaries. So code needs to become:

  :host {
    width: 200px; height: 50px;
    display: flex; justify-content: center; align-items: center;
    font-weight: 700;
    background-color: brown;
   }
   .container {
      background-color: grey;
      & .text {
        color: gold;
      }
    }
  }
Sign up to request clarification or add additional context in comments.

1 Comment

very thanks, I got it ~

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.