polyfills icon indicating copy to clipboard operation
polyfills copied to clipboard

[ShadyCSS] Constructible Stylesheets and adoptedStyleSheets support for browsers with native shadow DOM

Open justinfagnani opened this issue 5 years ago • 4 comments

Constructible Stylesheets

We want to support and API as close as possible to native Constructible Stylesheets, so that this works:

const s = new CSSStyleSheet();
s.replaceSync(':host { display: block } ');

This may be achievable by overwriting the CSSStyleSheet constructor with one that creates a stylesheet in a shadow root. Something like:

const container = document.createElement('constructible-stylesheets');
container.attachShadow({mode: 'open'});
document.append(container);

const originalCSSStyleSheet = CSSStyleSheet;
CSSStyleSheet = class extends originalCSSStyleSheet {
  constructor() {
    this._styleElement = document.createElement('style');
    container.shadowRoot.append(this._styleElement);
    Object.setPrototypeOf(this, this._styleElement.sheet);
  }

  replaceSync(styleText) {
    this._styleElement.data = styleText;
  }
}

(I haven't tried this code)

adoptedStyleSheets

ShadowRoot.adoptedStyleSheets could be implemented with a setter that only accepts arrays of stylesheets created as above with a _styleElement property. It would then clone those style elements and insert them last into the shadow root.

To protect against mutations of the shadow root that remove the styles, we can put them in a custom element called <adopted-stylesheets> that adds itself back to the shadow root if it's ever removed.

const allAdoptedStylesheets = new Set();
class AdoptedStylesheetsElement extends HTMLElement {
  constructor() {
    super();
    allAdoptedStylesheets.add(this);
  }

  connectedCallback() {
    this._previousRoot = this.getRootNode();
  }

  disconnectedCallback() {
    this._previousRoot.append(this);
  }
}

allAdoptedStylesheets can be used to update cloned style tags incase replace or replaceSync is called on a CSSStyleSheet.

cc @azakus

justinfagnani avatar Apr 17 '19 19:04 justinfagnani