Vuejs .vue file: dynamic less import - css

I have a Vue app composed of several standard .vue files like this:
<template>
<h1>My App</h1>
</template>
<script>
export default {
name: 'app',
data () {
return {
cssTheme: 'default-theme'
};
}
}
</script>
<style lang="less">
#import "assets/constants";
html, body {
color: #color-ui-text;
}
</style>
In my assets/constants.less file I have defined many css variables to be used by less (colours, fonts and so on).
I want to give my app a serie of graphical "themes" that can be changed dynamically.
Given the variable cssTheme that I can read / set / change from the interface (and set it to strings like "green-theme", "vintage-theme", "default-theme"), how can I import and apply on the fly the appropriate less file into the <style> part of the .vue file? For instance, the user selects the "green-theme" and I want to switch the default imported file #import "assets/constants"; to #import "assets/constants-green"; where, for example, #color-ui-text; is set to dark green instead of the standard black.

If you use vue cli, you can use something like this:
module.exports = {
css: {
loaderOptions: {
sass: {
data: `
#import "assets/constants";
`
}
}
}
};
It will automatically add #import "assets/constants"; in each sass file
Note: i use sass in example
more about this you can find here:
loaderoptions

Related

How can I get gulp-sass to compile bootstrap CSS definitions rather than just output the import statement?

I'm trying to pull in the Sass bootstrap source (.SCSS), make some customisations (via another .SCSS) and spit out a CSS file.
I've been trying to use Gulp to do this is VS2019 using gulp-sass. I've followed many tutorials and have come up with the following gulpfile.js
var gulp = require('gulp');
var sass = require('gulp-sass');
sass.compiler = require('node-sass');
gulp.task('sass', function () {
return gulp.src('./Main.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
In my Main.css I have the following:
$theme-colors: ( "primary": #fd7e14 );
#import "//lib/bootstrap-4.4.1/scss/bootstrap";
body {
color: #5CFF54;
background: rgb(92,18,18);
height: 400vh;
}
However, the file that is being generated contains the following:
#import "//lib/bootstrap-4.4.1/scss/bootstrap";
body {
color: #5CFF54;
background: #5c1212;
height: 400vh; }
I was expecting it to pull all of the individual styles into the produced CSS file, not just add the import.
Can anyone point me in the right direction?
After much trawling of the internet I have discovered that this is expected behaviour, and is down to the way I am referencing the source bootstrap.scss file.
In short, I am referencing it with web path, this has the effect of adding an import statement to the produced .css file. If I change the reference to a filesystem path such as this:
#import "../lib/bootstrap-4.4.1/scss/bootstrap";
it functions as I had hoped and the produced .css file includes all of the definitions from bootstrap.scss.

Import only one CSS class from another Sass file

Consider this code:
// File A1.scss
.abc {
// styles for abc
}
.def {
// styles for def
}
// File B2.scss
.xyz {
// styles for xyz
}
Is it possible to import and use .abc from A1.scss into B2.scss without having the class .def in B2.css (i.e. the output of B2.scss)?
A1.scss is large in real project, so can't afford to have B2.scss be bloated with other styles. I am using this in a React app with Webpack.

CSS className isn't making any changes to Reactjs

I'm currently working with rails and reactjs. I'm having difficulties using css in my reactjs files. It seems like every time i try to use it, no change is being applied at all. In my App.jsx file I have this:
import React from "react";
import styles from "./styles.css";
export default class Register extends React.Component {
render() {
return (
<div className={styles.container}>
<h1> this text should appear to the right </h1>
</div>
);
}
}
And in my styles.css file I have this:
.container {
width:40%;
text-align:right;
}
For the record I am using webpack. Can anyone help me understand why the css isn't having any effect on my jsx components. I've looked all over for help but was unable to put the pieces together.
If it matters, this is how my "config/webpack/development.js" file looks like:
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()
It depends on the webpack loader settings. If you are using css-loader as configured in react-scripts (as of 1.1.5), then the classNames are loaded using {modules: false} option, i.e. global styles, which can be referenced as strings in JSX code:
import "./styles.css";
... className="container" ...
Or you can load local styles using following CSS-file syntax:
:local .container {...
Or edit your webpack.config.js appropriately (see https://github.com/webpack-contrib/css-loader#scope for the official documentation of various options).
seems like you didn't enable an option { modules: true } for css-loader in webpack config
take a look
webpack-contrib/sass-loader#206
https://github.com/webpack-contrib/css-loader#options
Taken from: https://github.com/facebook/create-react-app/issues/1350

Best way to have global css in Vuejs

What is the best way to have a global css file in Vuejs for all components? (Default css like bg color, button styling, etc)
import a css file in the index.html
do #import in main component
put all the css in the main component (but that would be a huge file)
Import css in your index.html, but if you're using webpack you can just import your stylesheets in your main js config and all your components will get the css.
As comments below suggested if using webpack adding this to main.js works:
import './assets/css/main.css';
I found the best way is to create a new file in the assets folder, I created as global.css but you can name anything of your choice. Then, import this file global.css file in the main.js.
Note: Using this approach you can also create multiple files if you think the global.css is getting really large then simply import all those files in the main.js.
#\assets\global.css
/* move the buttons to the right */
.buttons-align-right {
justify-content: flex-end;
}
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './routes'
Vue.config.productionTip = false
// Importing the global css file
import "#/assets/global.css"
new Vue({
router,
render: h => h(App)
}).$mount('#app')
In App.vue you can add a style property to declare you CSS file:
<style>
#import './assets/css/global.css';
</style>
You can also do something like this: https://css-tricks.com/how-to-import-a-sass-file-into-every-vue-component-in-an-app/
My folders are mostly structured like this:
- src
- assets
- _global.scss
- _colors.scss
- _fonts.scss
- _paragraphs
- index.scss // <-- import all other scss files.
This also works with normal css.
create a new css file in your assets folder for example : global.css
import "global.css" to main.js
import '#/assets/main.css';
There are to two ways, as I know, to achieve this.
Approach 1
Utilize vue.config.js configuration, less config can also be replaced with sass:
module.exports = {
css: {
loaderOptions: {
less: {
additionalData: `#import '#/style/common.less';`
}
}
}
}
Approach 2
In your .vue file, make your style looks like this:
<style lang="less">
#import (reference) "../../style/variables.less";
#app {
background: #bgColor;
}
</style>
Note: the (reference) flag is used to make variables defined in variables.less take effect. If you don't have variables, #import "../../style/variables.less"; is sufficient to do the trick.
For your reference, you can also take a look at this link:
https://github.com/tjcchen/vue-practice/tree/master/multipage-app
Sass announced their new module system. Why don't you use #use and #forward?
My approach is the best way to use scss with vite.
Use defineConfig to setup global scss (colors, mixin) and reuse in all component without import
css: {
preprocessorOptions: {
scss: {
additionalData: `#use "~/styles/main.scss" as *;`,
},
},
},
Here: code sandbox
create a vue.config.js file in your root directory
Create a styles folder inside your src folder and you can create your global style file here for example base.scss
to use scss install two dependencies
npm install node-loader sass-loader
Inside your vue.config.js paste code from below
module.exports = {
css: {
loaderOptions: {
sass: {
additionalData: `#import "#/styles/base.scss";`
}
}
}
};

Using css-loader inline with Webpack + React

I'm building my React app with Webpack, and css-loader w/modules. I love it. Most of my stylesheets are very small, though, and I'd like to inline them within the same JSX file as my markup and JavaScript.
The CSS loader I'm using right now looks like this:
{ test: /\.(css)$/i,
loader: ExtractTextPlugin.extract("style-loader", "css-loader?modules") }
In my JSX, I import my separate CSS files like this:
import classNames from 'dashboard.css';
...
<div className={classNames.foo}></div>;
This is then compiled and translated into something like:
<div class="xs323dsw4sdsw_"></div>
But what I'd like to do is something more like below, while still preserving the localized modules that css-loader gives me:
var classNames = cssLoader`
.foo { color: blue; }
.bar { color: red; }
`;
...
<div className={classNames.foo}></div>;
Is this possible? How can I do this without having to actually require / import a separate file?
I believe your issue is that you your current webpack configuration uses CSS Modules. CSS Modules automatically rename your CSS Classes to avoid global class name collisions.
The fix:
// remove 'modules' from the end of your css-loader argument
{ test: /\.(css)$/i,
loader: ExtractTextPlugin.extract("style-loader", "css-loader?modules") }
// like so
{ test: /\.(css)$/i,
loader: ExtractTextPlugin.extract("style-loader", "css-loader") }
Now your class names will be preserved. Although, I'm not sure why you want to do this. Do you care to share why?

Resources