Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import CSS file content into a Javascript variable

Consider a very simply custom element using shadow DOM:

customElements.define('shadow-element', class ShadowElement extends HTMLElement {
  constructor() {
    super();
    this.styleTag = document.createElement('style');
    this.styleTag.textContent= `
.root::before { 
  content: "root here!"; 
  color: green; 
}
    `
    this.shadow = this.attachShadow({mode: 'closed'});
    this.root = null;
  }
  
  connectedCallback() {
    this.root = document.createElement('div');
    this.root.className = 'root';
    this.shadow.append(this.root, this.styleTag);
  }
})
<shadow-element></shadow-element>

To get the CSS into the shadow DOM, I create a style tag, which I append into the shadow root. This is all working fine so far.

Now for more complex CSS I would like to author it in a file shadow-element.css which is in the same folder as shadow-element.js. Besides seperation of concerns I also want IDE syntax highlighting and -completion for CSS authoring, so I really want the CSS in a separate, dedicated file.

I want to import the contents of that CSS file into a Javascript variable, like

import styles from './shadow-element.css'; // obviously doesn't work

On the project where this is being used we have a working webpack stack that allows importing CSS (and even SCSS), but unfortunately that imported CSS then becomes part of bundle.css - which obviously is not at all useful, because the element uses shadow DOM.

Does anyone have a solution to this? I'm also open to alternative solutions, as long it won't require me to author my CSS in a .js file.

Edit: I am aware of the option of using @import './shadow-elements.css'; inside the style tag, but I would much prefer a solution that bundles the imported CSS into my Javascript bundle (as part of the component code).

like image 817
connexo Avatar asked Aug 12 '19 11:08

connexo


1 Answers

As you are using webpack, you can use raw-loader to import a text file (CSS in your case) into a string:

npm install raw-loader --save-dev

And you can use it inline in each file:

import css from 'raw-loader!./shadow-element.css';

customElements.define('shadow-element', class ShadowElement extends HTMLElement {
  constructor() {
    super();
    this.styleTag = document.createElement('style');
    this.styleTag.innerText = css;
    this.shadow = this.attachShadow({mode: 'closed'});
    this.root = null;
  }

  connectedCallback() {
    this.root = document.createElement('div');
    this.root.className = 'root';
    this.shadow.append(this.root, this.styleTag);
  }
})

like image 92
Ander Avatar answered Sep 28 '22 03:09

Ander