Lack of styling during the development of a Vue web component

During the development of a Vue web component, I encountered an issue where the CSS styling was not being applied to the web component itself, but instead added to the head of the document. This resulted in the style being ignored within the shadow DOM. To address this, I wrapped the web component in my main.js file like so:

import Vue from 'vue';
import wrap from '@vue/web-component-wrapper';
import MyWebComponent from './components/MyWebComponent';

const WrappedElement = wrap(Vue, MyWebComponent);

window.customElements.define('my-web-component', WrappedElement);

Despite these efforts, the CSS rules within the style tags continued to have no effect.

Interestingly, when I built the application for production, the styles were properly added to the web component. The command I used for wrapping during production build was:

vue-cli-service build  --target wc --name my-web-component ./src/components/MyWebComponent.vue

I am now wondering if there is a way to achieve the same result using vue-cli-service serve.

For reference, here is a link to an example repository: https://github.com/snirp/vue-web-component

After some investigation, I suspect that my problem may be related to this particular issue. While the provided workarounds are confusing to me, I would greatly appreciate a more straightforward solution.

Answer №1

After reviewing the GitHub issue provided, it appears that the recommended solution involves adjusting the shadowMode setting in both the vue-loader and vue-style-loader. It's worth noting that by default, shadowMode is set to false within a Vue CLI project, but this can be modified through the vue.config.js file.

To identify which loaders require changes, the Webpack configuration can be inspected with the following command:

# execute at the root of the project
vue inspect

The inspection results display multiple loader configurations where shadowMode: false is specified:

/* config.module.rule('css') */
{
  test: /\.css$/,
  oneOf: [
    /* config.module.rule('css').oneOf('vue-modules') */
    {
      resourceQuery: /module/,
      use: [
        /* config.module.rule('css').oneOf('vue-modules').use('vue-style-loader') */
        {
          loader: 'vue-style-loader',
          options: {
            sourceMap: false,
            shadowMode: false  // <---
          }
        },
        /* ... */
      ]
    },
    /* ... */

A comprehensive list of Webpack loader configs featuring shadowMode: false:

List of loader configurations...

To address this, updating the configurations to have shadowMode: true in the vue.config.js file can be achieved using this code snippet:

Vue.configurations('/vue.config.js', (configs) => {
  const updatedConfigs = [...];  // Insert updated configurations here
  
  updatedConfigs.forEach((config) => {
    if (config.shadowMode === false) {
      config.shadowMode = true;
    }
  });
});

By incorporating the above script into your project's

<projectroot>/vue.config.js
, you will enable Shadow CSS during development mode. Refer to this link for more details.

Answer №2

A revamped solution inspired by @tony19's initial answer, incorporating a script to dynamically set shadowDom to true for all components without the need for manual listing.

function applyShadowCss(config) {
  const configs = [
    config.module.rule('vue').use('vue-loader'),
  ];

  // Identifying common rule sets obtained from `vue inspect`
  const ruleSets = ['css', 'postcss', 'scss', 'sass', 'less', 'stylus'];
  const ruleNames = ['vue-modules', 'vue', 'normal-modules', 'normal'];

  ruleSets.forEach((ruleSet) => {
    if (config.module.rules.store.has(ruleSet)) {
      ruleNames.forEach((rName) => {
        if (config.module.rule(ruleSet).oneOfs.store.has(rName)) {
          if (config.module.rule(ruleSet).oneOf(rName).uses.store.has('vue-style-loader')) {
            configs.push(config.module.rule(ruleSet).oneOf(rName).use('vue-style-loader'));
          }
        }
      });
    }
  });

  // Setting build mode based on configuration
  if (!process.env.BUILD_MODE) {
    process.env.BUILD_MODE = config.store.get('mode');
  }

  // Applying shadowMode property to each option object in configs array
  configs.forEach((c) => c.tap((options) => {
    options.shadowMode = true;
    return options;
  }));
}

// Exporting module with customized CSS settings
module.exports = {
  css: {
    extract: false
  },
  chainWebpack: (config) => {
    applyShadowCss(config);
  },
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to adjust the font color when the expiration date passes?

My goal is to change the color of text to green when the expiration date has not been reached yet. If the expiration date has passed, then the text should be red. .curentDate { color: rgb(54, 168, 54) } .expirationDate{ color: red; } <div cl ...

Tips for evenly distributing list elements in HTML without using whitespace

After reading the article on flexbox techniques without actually using flexbox, I attempted to implement "space-between" in my code: ul { margin: 0; padding: 0; text-align: justify; } ul:after { content: ""; display:inline-block; width:100%; ...

When a link is clicked, it quickly blinks or flashes on the screen

https://i.sstatic.net/cCFmX.gif <div class="collapse navbar-toggleable-xs" id="exCollapsingNavbar2"> <%= link_to 'FARDIN KHANJANI', root_path, class: 'navbar-brand logo' %> </div> Upon viewing the gif I include ...

Leverage JavaScript or CSS to create a paper button without the ink effect

Currently, I am utilizing JavaScript to dynamically create paper-buttons in the following manner: function createButtons(dieDefaults) { for(var i = 0; i < dieDefaults.length; i++) { var btn = document.createElement("paper-button"); var txt = d ...

What is the method to fetch CSS properties in relative units like percentages and ems using the .css() function with the selector "$("selector")"?

Using jQuery to retrieve HTML element's css properties hasn't been as effective as desired. To test this issue, the following experiment was conducted: var div = document.createElement("DIV"); div.id = "testdiv"; var testZero = $(div).css("w ...

Storing arrays of objects in Laravel involves creating models, defining relationships between them,

I am in a situation where I have a form set up with specific input fields for shipping rules. The form structure is as follows: <shipping-rules-form> <div class="row" v-for="(input,index) in form.inputs" :key="index&qu ...

Add content to the beginning of the input with the assistance of bootstrap. However, ensure that when utilizing "form-group row", the content is shifted

I am experiencing an issue with my Bootstrap 4 form. I am using the 'form-group row' class to display labels and inputs on the same line, but when I try to prepend a $ sign before an input, it shifts the input to the next line. Below is the code ...

Vue.js tutorial: Disabling button dynamically based on empty data array

My project involves creating a shopping cart application using Vue.js: var app = new Vue({ el: "#app", data: { items: [ { id: 1, name: "Item 00", spec: "spec 00", price: 400, quantity: 1, unit: &quo ...

Encountered a problem resolving the asynchronous component rendering with View-Router

While attempting to integrate VueJs with VueRouter, I encountered a problem. The Home component is displaying the log message but not the template section. Additionally, an error was thrown as shown below: https://i.sstatic.net/2YWQL.png Home.vue <te ...

Could someone lend a hand in getting the X to align properly on this div? I've been struggling with it for ages and just can't seem to crack

This is a demonstration of the CodePen project: Click here to view <div class="annotation"> <div class="annotext"> <div class=annobar></div> <div class="x">✕</div> Lorem ipsum dolor sit amet, consectetur adipiscing e ...

HTML/CSS: What could be causing the iframe to not scroll properly?

I am facing an issue with my website that has 3 iframes, none of them seem to be working properly. In Firefox, the scroll bars appear but do not function, while in Chrome, the scroll bars do not appear at all. Surprisingly, they work fine in IE 6. This pr ...

Is it possible to incorporate Google icons within Freemarker?

https://i.stack.imgur.com/Pv2T4.pngI'm having trouble using Google icons in my project. Can anyone help me figure out how to fix this? UPDATE: Here is a snippet of my HTML template: <?xml version="1.0" encoding="UTF-8"?> < ...

Is there a way to eliminate the legend symbol for just one legend in Highcharts?

Looking to customize a legend in Highcharts but facing limitations due to Plot Lines and Bands not having legends. To work around this, I have added an empty series that acts as a toggle for showing/hiding plot lines. Since my plot lines are vertical, I im ...

Aligning SVG clipping path using CSS

This problem has me stumped! I need to center the SVG clip within the surrounding div, just like in this example: http://jsfiddle.net/ztfdv9qh/ - Make sure to check the link because the SVG is quite long! <div class="svg-wrapper"> <div class ...

Is it possible to seamlessly incorporate a square image into a bootstrap background image slider without having to crop the image?

I've exhausted all the different solutions I've come across on other platforms to resolve this issue, but I'm still unable to find a fix. So here's what I'm struggling with: The problem I'm facing involves finding the correct ...

Adjusting the height of a div based on the height of the window

Here is the HTML structure I am working with: <body> <div class="header">header</div> <div class="content"> hello </div> <div class="footer">footer</div> </body> This is the current ...

Issue with Hover behavior not being implemented on Android Webview

On my webpage, I have multiple CSS hover styles implemented using both the :hover pseudo selector and the cursor property. However, when loading this webpage in an embedded WebView on an Android device equipped with a mouse (such as Chromebooks), the CSS h ...

Iconic Side Navigation with collapsed button malfunctioning due to negative positioning

I'm facing two issues with my webpage. First: I have three buttons on the right side of my page that are supposed to behave like the buttons on this example. However, when you scroll, you can see that their position is incorrectly displayed "outside" ...

Is there a way to customize the hover effect on this navigation link in Bootstrap that includes a span and an icon from Bootstrap?

<li class="nav-item mt-3"> <a href="#" class="nav-link px-2 d-flex justify-content-start align-items-center"> <i class="nav-icon bi bi-calculator-fill fs-4"></i> ...

manipulating child element's innerHTML with javascript

Is there a way to change my icon from expand_more to expand_less in the code below? <li class="dropdown-bt" onclick="dropdown('content');"> <a>dropdown-content <i class="material-icons">expand_more</i></a> </ ...