How to inject Global constant to a vue component <style>? - vue.js

I'm searching how to inject a global (THEME_NAME in my example) to all the vue components:
<template>..</template>
<style lang="scss">
#import "bulmaswatch/<%=THEME_NAME=>/bulmaswatch.scss";
.foo {
color: $primary;
}
</style>
Context:
I'm using the darkly theme of bulma css in my vue application (vue Cli 3)
<template>..</template>
<style lang="scss">
#import "bulmaswatch/darkly/bulmaswatch.scss";
.foo {
color: $primary;
}
</style>
In order to switch to the cyborg theme, I will have to replace darkly with cyborg everywhere...
Is there a better way? Something like
<template>..</template>
<style lang="scss">
#import "bulmaswatch/<%=THEME_NAME=>/bulmaswatch.scss";
.foo {
color: $primary;
}
</style>
then somewhere in Webpack or vue.config.js, we can decide what is the theme
configureWebpack: () => {
return {
plugins: [
new webpack.DefinePlugin({
THEME_NAME: "cyborg"
}),
],
}
}

In order to switch to the cyborg theme, I will have to replace darkly with cyborg everywhere...
Not if you use the re-export pattern.
There's no need for any external libraries and codegen magics with webpack.
Basically, you create a file where you import your theme.
Let's call it _my-bulma-theme.scss and let's import darkly for now.
// _my-bulma-theme.scss
#import "bulmaswatch/darkly/bulmaswatch.scss";
In your code, you import this file instead of importing from Bulma directly:
// some-component.vue
<style>
#import "../../my-bulma-theme";
</style>
// some-other-component.vue
<style>
#import "../../my-bulma-theme";
</style>
Now, when you want to change the theme, you just need to change it in one place: the _my-bulma-theme.scss file.
// _my-bulma-theme.scss
#import "bulmaswatch/cyborg/bulmaswatch.scss";

Related

Undefined mixin sass

I get error undefined mixin when i use #include in components
I work in NuxtJs, install sass-loader, node-sass
Component
<style lang="scss">
.cardSmall {
#include mq(laptop) {
width: 720px;
}
}
</style>
My mixin in assets/variables.scss
#mixin mq($breakpoint) {
#if $breakpoint==laptop {
#media only screen and (max-width: 991px) {
#content
};
}
}
Nuxt imports several things automatically such as components and composables. But it doesn't auto-import (sass) mixins. Therefore you need to add an import to the top of your <style /> tag:
<style lang="scss">
#use "#/assets/variables.scss";
// ...
</style>

Why do SCSS variables imported from another file doesn't work in Vue 3?

I have installed sass loader in my vue 3 project, but the issue is that I want to import variables from another file, but doesn't work
my schema is:
src
assets
scss
styles.scss
_variables.scss
styles.scss
#import url('./_variables.scss');
body{
font-family: 'Montserrat';
background-color: $primary-black;
}
.sidebar{
width: 250px;
height: 100vh;
max-height: 100vh;
background-color: $primary-black;
}
_variables.scss
$primary-black: #222222;
App.vue
Some HTML
<script>
import Sidebar from './components/Sidebar';
export default {
components: { Sidebar },
setup() {
},
}
</script>
<style lang="scss" scope>
#import url('./assets/scss/styles.scss');
</style>
And the issue is that in the browser the $primary-black variable fails, it appears background-color: $primary-black literally, I mean doesn't take de "#222222" color instead, but if I change the variable, and put it inside the styles.scss file, it works, so I'm not sure what could be the problem
Do not use the url function while importing, try the below
<style lang="scss" scope>
#import './assets/scss/styles.scss'
</style>

How to use .less file in nuxt js

I created a .less file in my assets/css/myfile.less Nuxt folder and I added some CSS to it.
.edit-btn-color {
background-color: #b1c646;
color: white;
}
.edit-btn-color:hover {
background-color: darken(#b1c646, 10%);
color: white;
}
and in nuxt.config.js I do the following:
export default {
less: ['#/assets/css/myfile.less'],
}
But it does not work.
Since Nuxt2 is still using Webpack4, you need to install the v7 of less-loader (v8 is using Webpack5)
yarn add less-loader#^7 less
Then, create a .less file somewhere, like /assets/css/myfile.less
And use it in nuxt.config.js with this
export default {
css: ['~/assets/css/myfile.less'],
}
The key to use here is css, it's the same for SCSS, SASS, Less, Stylus and so on, as shown in the documentation: https://nuxtjs.org/docs/2.x/features/configuration#the-css-property
The answer for Nuxt v3 would be:
Install Less: npm i less (no less-loader needed).
For Global styles add them to your nuxt.config.ts like this:
export default defineNuxtConfig({
css: ['~/assets/less/main.less'],
})
In your components you could use Less like this:
<style lang="less" scoped>
#import (reference) '../assets/less/helpers.less';
nav {
background-color: darkkhaki;
.my-great-style; /* Imported from helpers.less */
}
</style>

Importing SASS variables into Vue component

I'm working on building a webpage using Vue, Typescript, Webpack, and Bulma. I got everything working and building correctly but I noticed that some of my bundles were massive (over 2mb in some cases). After a lot of confusion I figured out it was because I was importing my main SCCS file that included Bulma, Bulma Fluent, and Material Design Icons into my components so that I could use the variables, mixins, and extend some of the classes. From what I understand #import simply copies everything from the import, which would explain my massive bundles.
A close approximation of my working code:
main.scss
/*Color customizations*/
#import "bulma-fluent/bulma.sass";
#import "buefy/src/scss/buefy";
#import "#mdi/font/scss/materialdesignicons";
/*Some custom classes*/
MyComponent.vue
/*Template and Script here*/
<style scoped lang="scss">
#import "./main.scss";
.floating {
#extend .m-1;
position: fixed;
bottom: 0;
right: 0;
}
#include mobile {
.floating {
max-width: unset;
left: 0;
}
}
</style>
I want to be able to reference classes/variables/mixins from my main.scss without it ballooning the size of my modules. I thought about creating a separate variables.sass file but I couldn't get that to work plus it doesn't fix the issue of extending styles. I saw this question but I'm not using Nuxt.
How can I get this working?
P.S. I'm a bit of a noob when it comes to Webpack/Vue/SASS/SCSS so I apologize if I'm just being dumb here.
Edit
In the end I split out the variables to their own file and imported those globally. It doesn't solve the use case of extending styles but I think that's a lost cause. My code is below:
Variables.scss
/*Customization here*/
#import "bulma/sass/utilities/functions.sass";
#import "bulma-fluent/src/sass/color/_all.sass";
#import "bulma/sass/utilities/initial-variables.sass";
#import "bulma/sass/utilities/derived-variables.sass";
#import "bulma/sass/utilities/mixins.sass";
Main.scss
#import "./Variables.scss";
#import "bulma-fluent/bulma.sass";
#import "buefy/src/scss/buefy";
#import "#mdi/font/scss/materialdesignicons";
/*Some custom classes*/
webpack.js
/*Other irrelevant configurations*/
{
test: /\.s[ac]ss$/,
use: [
"vue-style-loader",
"css-loader",
{
loader: "sass-loader",
options: {
additionalData: `
#import "./Variables.scss";
`
}
}
]
},
MyComponent.vue
/*Template and Script here*/
<style scoped lang="scss">
.floating {
margin: $size-1;
position: fixed;
bottom: 0;
right: 0;
}
#include mobile {
.floating {
max-width: unset;
left: 0;
}
}
</style>
I use the same stack. I have variables.scss file with variables and bulma mixins and that variables.scss file is imported only in main.scss .
To make all variables and mixins available in all components without using #import in style section you should add loaderOptions section to vue.config.js file. Here is my vue.config.js file:
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: '#import "~#/assets/scss/_variables.scss";'
}
}
}
}

How do I #extend external CSS classes in a Vue component?

For example, if I have something like this in my component:
<style lang="scss" scoped>
.color-blue {
color: blue;
}
.orange-blue {
#extend .color-blue; // This works!
#extend .bg-orange; // .bg-orange is defined in another css file somewhere. This doens't work
}
</style>
I get an error that says
".orange-blue" failed to #extend ".bg-orange".
The selector ".bg-orange" was not found.
I've read that I can add
#import 'path/to/orange.css'
to my style block, but that doesn't seem to do the trick here. Also, wouldn't that result in the CSS being repeated for every component that imports it?
Import the file with other styles like that
<style lang="scss" scoped>
#import '~styles/mixins';
...
</style>
or use the usual path
#import '../../../styles/mixins';
You can do it the following way:
Create the file containing the class you want to extend:
src/styles/style.scss
.my_class_to_extend {
backgroud-color: aqua;
}
In your vue.config.js file you add the following pointing to your file:
module.exports = {
css: {
loaderOptions: {
sass: {
data: `#import "#/styles/style.scss";`
}
}
}
}
After that you can extend in your vue component without problems:
...
<style lang="scss" scoped>
.my_extended_class {
#extend .my_class_to_extend;
}
Note that to use that you need scss files all along, not css.
In short, you can not extend css class in *.scss file by importing plain *.css file. Scss compiler will throw an error SassError: The target selector was not found.
The easy way is to rename referenced *.css file to *.scss. So outcome would be like #import 'path/to/orange.scss'