Open keithamus opened 6 months ago
Some assorted thoughts:
The primary use case cited is for adopting document.styleSheets
, but this will also enable adopting stylesheets from a parent shadow-root (which is equally useful!)
const parentRoot = el.shadowRoot.host.getRootNode();
el.shadowRoot.adoptedStyleSheets.push(
...parentRoot.styleSheets,
...parentRoot.adoptedStyleSheets,
);
I think there is (or should be) a difference between "constructed" stylesheets and "adoptable" stylesheets.
Regular document .styleSheets
are obviously not constructed. Similarly, there might be a way to write declaratively adopted stylesheets in the future; these wouldn't be constructed either.
The @import
restriction could continue to apply to constructed stylesheets, but does not need to apply to other adopted stylesheets.
Should there be an easier way to feature detect?
Currently I can see a try
/catch
way of polyfilling.
function requiresConstructing() {
try {
const doc = document.implementation.createHTMLDocument();
doc.body.appendChild(doc.createElement("style");
doc.adoptedStyleSheets = doc.styleSheets;
return false;
} catch {
return true;
}
}
el.shadowRoot.adoptedStyleSheets.push(
...constructIfNecessary(document.styleSheets),
...document.adoptedStyleSheets,
);
function constructIfNecessary(styleSheets) {
if (!requiresConstructing()) return styleSheets;
return Array.from(styleSheets).map(styleSheet => {
const sheet = new CSSStyleSheet();
sheet.replace(stringifyStyleSheet(styleSheet));
return sheet;
});
}
(using stringifyStyleSheet
helper from #7171)
Should there be a way to adopt stylesheets not just once, but "forever"?
If I understand correctly, adoptedStyleSheets.push(...document.styleSheets)
is taking a snapshot of document.styleSheets
at the time it's called. styleSheets
could change in the future, and it's probably desirable to propagate those changes into wherever they are adopted.
Edit: maybe the changes to the original styleSheets do get reflected automatically, but using ...
means you do not get any new styleSheets that were created later. For this reason, maybe adoptedStyleSheets
should accept a StyleSheetList
?
- el.adoptedStyleSheets.push(...document.styleSheets);
+ el.adoptedStyleSheets.push(document.styleSheets);
The CSS Working Group just discussed [cssom] Can we lift the restriction on constructed flag for adoptedStylesheets?
, and agreed to the following:
RESOLVED: We do want to remove this restriction, and will work on how to address this
My question to this, how can the styles be shared between two windows? Problem now is, you can move a webcomponent with adoptedStylesheets to a new window (via adoptNode) but then you need to copy all the styles. Also the component can not do this itself, cause the adopted callback is fired when the component is adopted and then the adoptedStylesheets list is empty.
I did a hack here so it copies all the styles https://github.com/node-projects/dock-spawn-ts/blob/e90e3e50b7022e9525bdf8e53031e053ca86f4e0/src/BrowserDialogHelper.ts#L63 But I'd like to see platform support. It is usefull if you have a dockui like vscode (sample of such a ui with webcomponents https://node-projects.github.io/web-component-designer-demo/index.html)
Currently
adoptedStyleSheets
has a restriction onCSSStyleSheets
that have theconstructed
flag set:I'm here to rattle this Chesterton's fence. It would be really useful to be able to pluck a documents stylesheets and adopt it into a shadowroots
adoptedStyleSheets
, co-opting the pages styles while applying the shadow's own styles. Currently this is possible with a rather unfortunate amount of JS by duplicating a<link>
tag and stuffing it in your shadow-dom, but it feels like we can make this easier?(Cue discussion about
@import
and media queries...)