Vue including global styles without repeating the styles for each component - vue.js

I have an app and would like to include some global styles that I can use anywhere in the app like this:
.btn {
...
}
In webpack I already have this for _variables.scss to include things like $my-color: $fff and that is wired up like this in my loaderOptions:
{
additionalData: `#import "#/styles/_variables.scss";`
}
Obviously for some global styles I could do the same thing, however, this will cause my styles like .btn to load as many times as components that I have.
Logically it would seem best to just go into my root Vue component and add global <style lang="scss"></style>.
However, I am upgrading a legacy jQuery app and it is being piecemealed and instead of one root app component, I have several roots for parts that have been converted to Vue. I don't have a central place to load these styles.
For instance I have searchBar and checkout apps that are instantiated using Vue.extend (so they are all part of the same instance). There aren't just two apps, there are quite a few. If I include the global styles in the root of any of them it... feels... icky...
Is there any way around this or should I set the global styles in a random app with a TODO to refactor once everything is ported over?
Ideally I would do the same thing I'm doing with the _variables.scss but having the styles duplicated for each component is a non starter for me.

In this scenario you do not need to worry about how webpacks CSS loaders are working.
You can simply go into your main.js and import '#/styles/globals.scss' to load the styles globally.

Related

Exclude Bootstrap styling from certain routes in Vue.js

I have a single-page vue 2 app made with the cli-tool. Most of my routes use Bootswatch (Bootstrap) styling. But one shouldn't at all. This is only a problem because the Bootstrap affects the body and html styles and generally messes with the other styling. The route shouldn't use Bootstrap gets affected even when I #import the Bootstrap in a scoped <style> only to the routes that should use it. This happends if I first visit the Bootsrap routes and then to the isolated one. How should I go about doing this so that one of my routes is completely isolated when it comes to styling? If it's impossible or very impractical, suggest other ways of doing this. If this weren't a single-page-app this would be easy. But I'd prefer it be one.
I succeeded in encapsulating bootstrap import within a class called 'bootstrap-inside' and assigning it to the #app (Index route for example) div that is supposed to be styled with Bootstrap.
.bootstrap-inside {
#import '~bootstrap/scss/bootstrap.scss';
}
From now on, if you want to use bootstrap, you just have to use .bootstrap-inside in your component/view/layout.
I would suggest creating a view layout for your no-bootstrap pages and set your route to extends that layout (i can give you the solution for this too if you want).
I can mention this answer of another thread about limiting the scope of bootstrap styling in case you go through unexpected bootstrap behavior.
The easiest solution I know for this is to manually reset every css property for a given selector.
You could add an id / class to the root element of your page, and explicitly reset all css properties for all its childs. It would override the default bootstrap styles, but not remplacing its classes though.
Here's a class that would reset every css property: reset css for a div #15901030
It's not super convenient but it should work!

Disable Spartacus component styles

The documentation states that that component styles can be skipped
Skipping Specific Component Styles
Component styles are optional, because they are pulled in from the style library. Therefore, you might want to disable some standard component styles entirely. To disable standard component styles, you can add the component selectors to the $skipComponentStyles list. The following is an example that demonstrates skipping two standard components from the style library:
$skipComponentStyles: (cx-product-carousel, cx-searchbox);
$skipComponentStyles: (cx-product-carousel, cx-searchbox);
Skipping specific component styles might be beneficial if you need to create styles from scratch and do not want to override specific style rules coming from the Spartacus style library.
Where should this be done? I can't get that from the documentation. My first guess should be the global style.scss but for example the following does not work:
#import '~#spartacus/styles/index';
$skipComponentStyles: (header, cx-media, cx-banner, cx-category-navigation);
You're almost right, you just need to swap the 2 lines. The sass variable will be used inside the import of the Spartacus styles, otherwise the variable defaults to an empty var. so, the following will work:
$skipComponentStyles: (header, cx-media, cx-banner, cx-category-navigation);
#import '~#spartacus/styles/index';

Add SCSS file to VueJS app, but not each component

I have the feeling I'm thinking way too much into this, but I cannot find what I'm looking for in this pattern.
I have a VueJS app with several components and it all works. I'm using style-resources-loader to pull in my global variables and mixins and such into each component. This works as intended.
module.exports = {
pluginOptions: {
'style-resources-loader': {
preProcessor: 'scss',
patterns: [
path.resolve(__dirname, './src/styles/variables.scss'),
path.resolve(__dirname, './src/styles/text-mixins.scss'),
path.resolve(__dirname, './src/styles/interactive-mixins.scss'),
],
}
},
}
I also have an app-level style sheet. Resets, general layouts, etc. These are not things I want pulled into the SCSS processing of each component - just something I want output in the final CSS for the application.
Everything I find when looking for "how to add SCSS file to Vue" is all about the resource loader for the component processing. I cannot include the global styles in this way and then rely on de-duping to remove the extraneous ones - the imported global styles are being scoped by the built-in component scoping, which is causing bloat and is just generally a bad pattern.
I also don't want a separate Webpack build and CSS file as the end product if I can avoid it.
I can put this inside say the root level App style block, but that's not a great place to work with page-level CSS. It would be ideal to have this a/a set of SCSS files separate from components, but part of the Vue App's SCSS compiling.
Update
Had a big block of stuff here, not sure how it got in that state but that is not the case now and I cannot recreate it.
Throw them in your entrypoint.
Literally include the scss within the start. Like this in your app.ts or app.js :
import Vue from 'vue'
import Buefy from 'buefy'
import 'buefy/dist/buefy.css' <-- like this
Vue.use(Buefy)
If your webpack is setup correctly, e.g. Vue cli, then it doesn't care how the scss is found. It will just inject it globally. Vue components are also global unless you specify scoped scss.
Example from https://buefy.org/documentation/start/

Design: Two Vue Components That Share Similar Sass

I am debating about how I should design my Vue components. Here is the problem: I have two Vue components that share the same sass. However, each has a slightly different markup, state, and methods. I was wondering how I can reduce the amount of sass code repetition. I don't want to have essentially the same markup and styling twice in two different components. Therefore, I was wondering about what is the best way to go.
Possible Solution 1:
Make one base component that has the necessary sass that is used by both components. Include slots to pass the markup from the other two components. In the other two components, add the base component and pass markup to the slots. This reduces the amount of sass repetition by keeping all the common sass needed in the base component.
Possible Solution 2:
Create an extra sass file with all the common css and then just import it in the component files that need the styling. I am not sure if this is acceptable in the Vue world. I have never seen a project where the author has had a separate file for the sass. It's always just included in the single file component. In the styles directory, people usually only include the global variables and mixins. They don't include styles that are only used in two components.
Possible Solution 3:
Combine the two components into one and use booleans and conditionals to determine what markup and state to use in that one component. I feel like this is bad design because it's essentially like passing a boolean parameter to a function. It violates the Single Responsibility Principle. It diverges the component into two different parts and I feel like it's better to have two components rather than one when this happens in order to prevent the divergence.
Those are the only solutions I can think of so far other than repeating the sass in two different files. I am aware of mixins in sass, but I am not sure where I should place the mixin. Which directory would this go in and how would I organize it? Additionally, I am also aware of mixins in Vue, but I don't think Vue mixins allow sass to be placed in them. This is a big dilemma I'm having right now. Any help is appreciated. Thanks in advance.
Maybe became useful for you to use a module rule at the webpack.config for sass, where all vue components will share the same archive or variable (you choose!);
Explaining better
First, you must have the sass-loader in your app.
To know if you already have it at your application, check out your package.json and search for it. If you haven't... run: npm install -D sass-loader.
Now that you have it, you can set the following configuration at your webpack.config.js:
module: {
rules: [
// ... other rules omitted
{
test: /\.scss$/,
use: [
{
loader: 'sass-loader',
options: {
additionalData: `#import "resources/css/sass/_variables.scss";`
}
}
]
}
]
},
Everything that you put in additionalData is like if you were adding to all Vue Components. It should work fine.
But I don't have a webpack.config.js...
So, if you don't, don't worry. It will be your issue if you started the project using the #vue/cli.
1. Create a file at the root of your vue project called vue.config.js;
2. Paste inside of it the following code:
module.exports = {
css: {
loaderOptions: {
// pass options to sass-loader
// #/ is an alias to src/
// so this assumes you have a file named `src/variables.sass`
// Note: this option is named as "prependData" in sass-loader v8
sass: {
additionalData: `#import "~#/variables.sass"`
},
scss: {
additionalData: `#import "~#/variables.scss";`
},
less:{
// http://lesscss.org/usage/#less-options-strict-units `Global Variables`
// `primary` is global variables fields name
globalVars: {
primary: '#fff'
}
}
}
}
}
There is 3 different options: scss, sass and less. You choose one more convenient for you and delete the others.
I hope to have helped you!

Strange text in Vue.js

I am trying to develop an application using vue.js2. I am getting some strange texts in source code. You can see those texts in below image.
Could anyone say why it is coming ?
You might be using scoped attribute on styles tag in your .vue files to scope your styling to the component only.
Any styles scoped to a component using the <styles scoped> ... </styles> , the styles will be applied only to the elements in that component only.
So vue-loader which parses the .vue files uses PostCSS behind the scenes to achieve this by add adding those weird and unique data attributes.
See Scoped CSS for more info