With Chrome based browsers I would IMPORT a style sheet via: -
My component -
import sheet from '/Vanilla/ScrollGrid.css' assert {type: 'css'};
or calling user web page -
if (userStyles != undefined && userStyles != null) {
if (typeof userStyles == "string") {
let userStylesURL;
try
{
userStylesURL = new URL(userStyles, baseURL);
} catch (err) {
console.log(err.message);
}
if (userStylesURL != undefined) {
userSheet = (userStylesURL.protocol == "http:" || "htps:")
}
}
}
if (userSheet)
{
myCSSMod = await import(userStyles, { assert: {type: "css"}});
}
var x = new sg.ScrollGrid("myTable", dimCols, options, myCSSMod.default);
This would then allow me to load the stylesheets at run-time: -
My ScrollGrid component: -
if (userStyles != undefined && userStyles != null) {
if (userStyles.type == "text/css") {
this.#shadowRoot.adoptedStyleSheets.push(userStyles);
}
}
I can easily replace the module import with a dynamic LINK tag creation: -
let link = document.createElement('link');
link.href = "./toggle.css";
link.rel = "stylesheet";
link.type = "text/css";
this.shadowRoot.appendChild(link);
Now I want to support Safari and Firefox so am evaluating alternatives
But where I need help/advice is "How the replace the IMPORT method in my web-component?"
I've tried using the.SHEET attribute from the LINK element but fell fowl of the "must be a manufactured CSSStylesheet()" rule so only know three options. (NB: I would like my component to continue to support an optional StyleSheet parameter as a CSSStylesheet and not a String URL")
Have the calling page load the stylesheet via FETCH or some other means into a String. The caller could then call the CSSStylesheet(string) constructor and pass me the result. This sounds appealing as it allows small (very few rules) strings to be hardcoded as well as larger external CSS files to be catered for.
Change my parameter to be a URL string and create a runtime LINK element in my component.
Have a "disabled" STYLE tag pointing at the external URL and then get the innerHTML as a string. Don't know if innerHTML is populated for disabled style tags or if using a URL on a Style tag is now deprecated.
Web-Component -
if (userStyles != undefined && userStyles != null) {
if (userStyles.type == "text/css") {
this.#shadowRoot.adoptedStyleSheets.push(userStyles);
}
}
this.#shadowRoot.adoptedStyleSheets.push(sheet);
Any other options? Please feel free to voice preferences.
Thanks @slothscript but if I try: -
let sheet = new CSSStyleSheet();
sheet.replaceSync("@import url(http://localhost/styles.css);")
I get: -
@import rules are not allowed here. See https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418.
Anyway, it's all too messy so until Safari supports "Assert" syntax I'm going to use instanceof to check if the parameter is a URL in which case I'll append a LINK element, or CSSStyleSheet in which case I'll continue to: -
this.#shadowRoot.adoptedStyleSheets.push(userStyles);
For the curious, I'm doing this because I still want the encapsulation cake but give my component caller greater flexibility than is available with :slot and :part and -css-variables.