Ed Lucas
Ed Lucas

Reputation: 7355

Is it possible to prevent :root styles from bleeding into a shadowed component?

I've created a web component using Stencil that uses the shadow DOM and needs to ignore any CSS that has been added to the page (it has its own stylesheet). To that end, I've included the usual fix to the component stylesheet:

:host {
  all: initial;
}

This works to reset any base styles set on the page using the <style> tag or an external stylesheet. However, if an inherited style like font-size is defined on the :root or html elements, its value is used when computing a relative value (e.g. 1rem) instead of using the browser's base size or a font size specified in my component's CSS.

In this example, my dev tools are showing that a font-size: 160px value applied to the :root is being used to calculate the final font size for an element that has been given font-size: 0.875rem, even though I've used the CSS reset above and tried to apply my own base of 16px.

Dev tools displaying final result of 140px when using a font-size of 0.875rem

I've done a fair bit of research regarding styles applied to the :root element, but have not found an answer. Is there a way to override styles used to compute relative values if they are set on the :root?

Upvotes: 1

Views: 541

Answers (1)

Here is a playground: https://jsfiddle.net/WebComponents/L5kbf8qm/

<style>
  :root {
    font-size: 15px;
  }
</style>
<my-element all="initial"></my-element>
<my-element all="inherit">Note we get the UA 8px margin back</my-element>
<script>
  customElements.define("my-element", class extends HTMLElement {
    connectedCallback() {
        let all = this.getAttribute("all");
      this.attachShadow({mode:"open"})
          .innerHTML = `<style>`+
                       `  :host{all:${all}}` +
                       `  div{font-size:2rem;background:pink}`+
                       `</style>` +
                       `<div>Component all:${all}</div>`+
                       `<span id=result ></span><slot></slot>`;
      const add = (name) => {
        let size = window.getComputedStyle(this.shadowRoot.querySelector(name))["font-size"];
        this.shadowRoot.querySelector("#result").append(`${name} font-size is: `, size, document.createElement("br"));
      }
      add("div");
      add("span");
    }
  })
</script>

Upvotes: 0

Related Questions