Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using external CSS link ref in a web component

I am trying to use Bulma from CDN inside a custom web component, but it doesn't appear to be working.

I have this for my html:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>hello</title>
  <meta charset="utf-8">
</head>
<body>
    <my-element></my-element>
    <script src="index.js"></script>

</body>
</html>

And this for my js file:

const sheet = new CSSStyleSheet()

sheet.replace('@import url("https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css")');

class MyElement extends HTMLElement {
    connectedCallback(){
        let that = this
        let id = Math.random()
        this.id = id

        const shadowRoot = this.attachShadow({ mode: 'open' })
        shadowRoot.adoptedStyleSheets = [sheet]

        let child = document.createElement('button')
        child.classList.add("button")
        child.innerText = id

        child.id = count

        shadowRoot.appendChild(child)

        this.addEventListener('click', e => {
            e.target
            console.log(that.id)
            that.remove()
        })
    }
}

if(!customElements.get('my-element')){
    customElements.define('my-element', MyElement)
}

let count = Math.floor(Math.random() * 10) + 1
for(i = 0; i <= count; i++){
    let el = document.createElement('my-element')
    document.body.appendChild(el)
}

What is notable is that if I use sheet.replaceSync('button { color: green; }') instead of sheet.replace(...), it works fine. But why doesn't the external CSS link ref import work?

UPDATE: I realized I'm getting the following warning in the console:

index.js:6 @import rules are not allowed here. See https://github.com/WICG/construct-stylesheets/issues/119#issuecomment-588352418.

As a note, I am trying to use this approach so I can style multiple custom web components the same way, without needing to import the stylesheet multiple times.

Thanks!

like image 553
Dshiz Avatar asked Dec 05 '25 03:12

Dshiz


1 Answers

My approach would be to use a single instance for all your components, something like this:

import bulmaStyles from 'https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css';
const bulmaCSS = new CSSStyleSheet;
bulmaCSS.replaceSync(bulmaStyles);

export class Styles {
  static get bulma() { return bulmaCSS }
}

and then, in your components, import this class

import { Styles } from 'path/to/Styles.js';

class MyElement extends HTMLElement {
    constructor() {
      super();
      // and use it in the constructor after creating the shadow DOM
      this.attachShadow({ mode: 'open' })
      this.shadowRoot.adoptedStylesheets = [ Styles.bulma ];
    }
}

To be able to import the stylesheet's CSS into a variable, you need your build stack to support that. Webpack supports it e.g. with the help of webpack-raw-loader.

If you're not bundling your code, you will have to wait for CSS modules, or grab the styles from the DOM.

like image 110
connexo Avatar answered Dec 07 '25 17:12

connexo