Home > Blockchain >  How to build web component with styling library using vite and vue 3?
How to build web component with styling library using vite and vue 3?

Time:02-15

I am able to build vue web component and load it in other pages, but I can't find document how to correctly include a UI framework. It seems the web component is under shadowDOM and import css using style tag won't work.

(Add the CDN link in the template and style is applied) enter image description here

Any hint on any framework, Vuetify or Ant Design or Tailwind CSS will be appreciated.

Similar question: Vuetify build as Web component style not showing

CodePudding user response:

Using custom elements without Shadow DOM is trivial. Just add like the way you do traditionally. However, with Shadow DOM, things are tricky. Only inheritable CSS styles pass through the Shadow DOM. Everything else is blocked. No straight forward integration with existing design systems (Vuetify, Ant, etc.) is not directly possible if that library is only exposing global CSS.

If the design system or a component library is exposing styles i.e. css files for individual components, then you can that with some effort.

The best solution is to use constructable stylesheet. You can use a bundler like Webpack to load the stylesheet for individual component (if and only if it is provided) as a string and feed it to the stylesheet constructor method as illustrated here.

// Read SCSS file as a raw CSS text using Webpack/Rollup/Parcel
import styleText from './my-component.scss';

const sheet = new CSSStyleSheet();sheet.replaceSync(styleText);

// Use the sheet inside the web component constructor
shadowRoot.adoptedStyleSheets = [sheet];

However, Firefox and Safari are yet to implement it.

If you need a fallback, then there are ways that are not so clean. Approach is same. Import the CSS/SCSS as a string and using the template literal, add it to the element's inner style tag.

import styleText from 'ant/button.css';

class FancyComponent extends HTMLElement {

  constructor() {
    super();

    const shadowRoot = this.attachShadow({ mode: 'open' });

    shadowRoot.innerHTML = `
      <!-- Styles are scoped -->
      <style>
        ${styleText}
      </style>
      <div>
        <p>Hello World</p>
      </div>
    `;
  }
}

customElements.define('fancy-comp', FacyComponent);

This all relies on the assumption that ant/material/veutify is exposing styles as individual files instead of one global file.

Alternately, the browsers have started supporting the link tag inside the Shadow DOM. But again it is really useful if you have styles for individual components. Read more about that here.

  • Related