Vue.js CSS bundle precedence (?)

Viewed 1411

I have a weird issue with Vue.js CLI production bundling where I cannot quite pinpoint the root cause and I appreciate some help.

I have a Vue CLI 3 application with the following (relevant extract) in my main.js:

// Bootstrap
import "@/assets/bootstrap/bootstrap.scss";
import "bootstrap-vue/dist/bootstrap-vue.css";
import BootstrapVue from "bootstrap-vue";
Vue.use(BootstrapVue);

// Toastr
import Toastr from "vue-toastr";
import "vue-toastr/dist/vue-toastr.css";
Vue.use(Toastr, {
  defaultPosition: "toast-bottom-right"
});

Running this in my dev environment (npm run serve) CSS works fine.

When I run this after the production complilation (npm run build) some classes... are not applied and I cannot reason why. Given that the only difference I can see is the bundling process, I'm incline to look for an issue in that direction.

I customized the bundling as follow (relevant extract) in my vue.config.js:

cacheGroups: {
  icons: {
    name: "icons",
    test: /[\\/]node_modules[\\/](@fortawesome)[\\/]/,
    chunks: "all",
    priority: 3
  },
  vendors: {
     name: "vendors",
     test: /[\\/]node_modules[\\/]/,
     chunks: "all",
     priority: 1
  }
}

And, as result, my CSS bundled are correctly created as follows:

  • a vendor chunk that includes the Toaster CSS.
    This includes a 'toaster' class and a 'toaster-info' class (this latest has just a background-color)
  • a app chink that include my custom built bootstrap CSS.
    As much as the bootstrap files are in the node_modules folder and, as such, they should go in the previous chink, they get in here because I'm compiling them as import in a the SASS file above that actually comes from by code.
    This includes a 'toaster' class again.

Now, what I can see is that:

  • both chunks appear to be loaded by the browser
  • the markup correctly uses the 'toastr toastr-info'
  • only the 'toaster' class from app (bootstrap) is applied
  • the 'toaster' and 'toaster-info' class are totally ignored by the browser and the background color from 'toaster-info' is not applied

I tested this with several browsers to exclude any specific browser weirdness.
Browser computed styles shows that the classes are "excluded" for some reason I don't understand (with "excluded" meaning are in the style tree but strikethrough).

screenshot

Can anyone help me understand why this is happening?

Thank you.

1 Answers

This is purely a CSS problem.

Since your app and vendor CSS defines a .toast class style, whatever is loaded last is given the highest specificity.

I'm assuming all you're trying to do is change the default .toast background colour to white (instead of black) but you want to leave the more specific classes like .toast-info, .toast-success, etc as they are.

To do so (without altering the vendor files), you can change your .toast definition to...

.toast:not(.toast-info),
.toast:not(.toast-success),
.toast:not(.toast-warning),
.toast:not(.toast-error) {
  background-color: rgba(255, 255, 255, .85);
}

If you're using a pre-processor like Sass (which I think you are), this can be written more succinctly.


Ideally, the vendor files should have defined their styles like...

.toast {
  background-color: #030303;
}
.toast.toast-success {
  background-color: #51a351;
}

which would give the "info", "success", etc styles a higher specificity than the .toast class but it doesn't look like they do. Perhaps you could create a pull-request

Related