skip to Main Content

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")

  1. 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.

  2. Change my parameter to be a URL string and create a runtime LINK element in my component.

  3. 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.

2

Answers


  1. Chosen as BEST ANSWER

    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.


  2. To import a stylesheet you can do this in a style tag.
    @import url(https://urltostylesheet);

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search