Vue 3 CSS files overlapping on component switch - css

I've imported some CSS files with
<style scoped>#import "../assets/XYZ.css";</style>
in different components. Now whenever I switch components the CSS from the other component is loading as well. Let's say I switch from Home.Vue to Blog.Vue, then Home.Vue's CSS file will be imported into Blog.Vue too. Whenever I refresh, everything seems to be fixed. Adding scoped doesn't seem to work for me.
I am using vue-router to switch between components.
This is my relevant code:
main.js
import './assets/main.css';
^ This is a css file to be used across my website on every component
Home.Vue
<style scoped>#import "../assets/home.css";</style>
Blog.Vue
<style scoped>#import "../assets/blog.css";</style>

Related

How to pass css module styling to child compontents

Before I begin, my question is about vue and bootstrap, but can be applied to any project with multiple ui frameworks that share class names.
I have an older project that uses bootstrap 2.0.0. I added Vue for new modules and I want to use bootstrap 4 in those.
If I would just add bootstrap 4 a lot of the project will break so I need to add it only to the new modules but im running into some trouble. I tried a lot of things but without a perfect solution. Here are some of the things I tried:
Scoped CSS:
component1.vue
<style lang="scss" scoped>
#import "~bootstrap/scss/bootstrap"
</style>
Pros: Rest of application wont break (bootstrap4 is only applied to this module).
Con: Bootstrap 2 is also still applied to this module, breaking this module.
Most important con: Every vue module will load in the entirety of bootstrap 4. So if I made more vue components in te future (which I will) I will get insane overhead.
CSS Module:
component1.vue
<style lang="scss" module>
#import "~bootstrap/scss/bootstrap"
</style>
Pro over scoped: This module wont break since classnames are hashed
Con: Same mayor con as scoped: Mayor overhead with multiple vue components.
What I thought was the magic fix:
components.vue
<template>
<div class="vue-components">
<component1></component1>
<component2></component2>
</div>
</template>
<script>
import component1 from './component1'
import component2 from './component2'
export default {
name: 'components',
components: {
component2,
component1
}
}
</script>
<style lang="scss" module>
#import "~bootstrap/scss/bootstrap";
</style>
The idea here is to add bootstrap as a module in a wrapper vue file and importing every component in it so that we only load bootstrap 4 once for every vue component. However the child components (component1 and component 2) don't get access to the styling. So it seems that imports are excluded from the module styles.
How would I be able to add bootstrap only to the new Vue components without exposing the old code to it (and also shielding the new components from the old bootstrap 2)?

why in react version 16.8.6 css that required in component affects in an other components also all css apear in header Instead of chunk.css

i created two css file in my react app login.css and main.css then require login.css in login.jsx and main.css require for an other files but css writed in login.css affect to an other components. also With a little focus i find all css file loaded in header generally for all component
CSS imported inside a component it's not scoped by its own. If your CSS have a general rule it will influence the whole page.
Importing CSS inside a component is great because you will automatically remove it if you delete the component and, in case your component is loaded asynchronously with a chunk it can be imported later. That's depends on webpack settings.

Global styling vs local styling in VueJS

I'm building a project with .vue files which make it possible to write the CSS (SASS), JS and HTML in the same file.
I've decided to have some global components written in SASS on a assets/styles/app.scss file which will load my grid, variables and mixins.
On top of that, I want to be able to write some local SASS rules depending the component / page I'm on, seems pretty logical to want both in a project ...
Locally it looks like this:
<template>
</template>
<script>
</script>
<style lang="scss">
#import "assets/styles/app";
.my-style {
color: $my-variable;
}
</style>
It actually works, for instance I can use $my-variable in my local .vue file or any mixin I want. The problem is a VueJS project will grow and components will go together to display a page.
I noticed the global styling was loaded on each component, and the same rule is present in 5x, 10x when I open my chrome developer tool. This is still a very small project; all my styles are basically duplicated and loaded by the browser each time I add a component to the same page.
How do you avoid to load multiple times the global styles, while being able to use global SASS code in each components?
I've never worked with local mixed with global styling before, I preferred to just abstract totally the styling into a separated structure, but this is way more convenient to code with everything local in the same place.
What am I doing wrong here?
Detail: I'm on NuxtJS but I believe this issue is more related to VueJS overall.
Basically, every time you do an #import in your components it appends another copy to the main CSS file that Webpack generates.
Assuming you have the Webpack SCSS loader properly configured (which I believe you do since it compiles), you should be able to import the SCSS file once in your app.vue and the SCSS compiler will find it when it appends all other CSS.
For example, getting global fonts and mixins:
<style lang="scss">
#import url('https://fonts.googleapis.com/css?family=Lato:300,400,400i,700,900&subset=latin-ext');
#import "#/scss/mixins.scss";
</style>
Then create your CSS for each component inside the component's <style> section. Just make sure you add the lang="scss" so it all compiles.
You might also want to look into scss-resource-loader for Webpack. I think this is in the newest CLI builds, not sure about Nuxt.
in App.vue
<style lang="scss">
#import "assets/styles/common.scss";
</style>
OR
import compiled sass to css file in main.js
import './assets/styles/common.css';

What is a difference between importing global styles in angular-cli.json and adding them separately to every css in every component?

I have in styles in angular-cli.json "../node_modules/bootstrap/dist/css/bootstrap.min.css". Why when I remove these lines and I add to every css in every component #import "{correct path to every directory/node_modules/bootstrap/dist/css/bootstrap.min.css}"it doesn't work as before?
The styles from styles.scss or included in the angular-cli.json work globally on the page, whereas when imported - they work only for the specific component.
That being said, it's probably not working for you, because bootstrap adds some styles to i.e. <html> or <body> elements and your components cannot style these.
Most likely your AppComponent's locator (app-root or so) is placed inside <body>. It cannot style parents.
Bootstrap should be imported once in your global stylesheet, then bootstrap classes/components may be used in your entire application.
Styles imported in component decorators are encapsulated (by default) and should be used inside given component only. When you try to import Bootstrap to all your components, generated stylesheet is repeated many times.

Keeping CSS out of JS in Angular 2/Angular-CLI

By default, Angular 2 compiles the CSS into JavaScript, especially when using WebPack as in Angular-CLI. I would rather this not happen for a couple of reasons.
The first reason is that when I'm developing, I find it really helps to be able to see in the developer tools exactly what style sheet a specific style rule was coming from and what line number it was on. The second reason is that I think compiling CSS into the code kind of misses the point of good CSS, which is that you can apply a different style sheet and have an entirely different look and feel with the same markup.
Is there a flag somewhere that I can set to leave the CSS in .css files, where IMO it belongs?
This is the whole point of encapsulated components.
A component should have it's own styles encapsulated with it so it can be shipped with the styles.
Imagine you want to publish one of your components to be used by others, shouldn't it have its own styles with it ?
That means Angular needs a way to link those css to the component , thus seperates them into chunks and injects them into head tag.
To solve your problem though , you have couple of options :
1- Not using the Emulated Encapsulation :
Components by default have a property called encapsulation which is set to Emulated , you need to change it to None:
#Component({
encapsulation:ViewEncapsulation.None
})
Then , you can put all you css in the head tag your self like you'd do with a normal html page.
2- If the problem is theme ing , you can make your component themeable .
You can have a theme attribute for your component and then based on that change the styleing :
#Component({
selector:'my-component',
styles:[
`
:host{
[theme="blue"]{
change what ever you want :
h1{
color:blue;
}
}
}
`
]
})
And then , using this component would be like :
<my-component [attr.theme]='"blue"'></my-component> // would be blue theme
<my-component></my-component> // would be default
Go to your base Html file(where the root module, main app is injected) and link the CSS stylesheets in your header section.
Webpack will not include it in it's compiled/combined css file which is injected into the page. The css file will still be included at run time in the browser.
<html>
<head>
<base href="/">
<meta charset="utf-8">
<title>dummy</title>
<meta name="viewport" content="width=device-width">
//was not injected/modified by webpack
<link rel="apple-touch-icon" sizes="57x57" href="app/images/apple-icon-57x57.png">
//webpack's injected this below from other components's imported/inline css rules
<link href="index-c2cacb5fa3dfbca6116f4e4e63d5c3c7.css" rel="stylesheet"></head>
With angular-cli 1.6.5 you can do this:
ng serve --extract-css
You will still have the style-encapsulation features, but devtools will now point to the component css source file.
I use the angular-cli as well (v1.0.0-beta.22). When I am ready to build for production I run the following command:
ng build -prod -aot
This generates all my production-ready files (bundled, tree-shaken and minified etc). Of particular note is that it will generate two versions of the style sheets.
One in js:
styles.b2328beb0372c051d06d.bundle.js
And another version is plain css:
styles.4cec2bc5d44c66b4929ab2bb9c4d8efa.bundle.css
I run some post-processing on the css file with gulp and use the css version for my production build. I am not sure if the same holds true for lazy loading (where the cli will produced different chunks), but it works for sure when lazy loading is not being used (I haven't launched a production-ready project yet with lazy loading).
I also tried a build with JiT compilation:
ng build -prod
It also produced the raw/minified version of the css style sheet.
Now, I know for sure the folowing does NOT work:
ng build
This will produce all the css embedded within js file, styles.bundle.js.
Since you want to use the raw css file during development, the only workaround I can think of is that you run ng build -prod in order to get the css file. Copy/paste this manually into your assets folder. Run "format" on the file to un-minify the file. Then do a normal build with a modified index.html file referencing your raw css file, and removing the styles.bundle.js script reference. Not pretty, but it might work.
Put a wrapper class in html example-
<div class="component-1-wrapper">
all yout html here inside component-1-wrapper
</div>
Structure your sass(scss) in the following way. Since your styles are wrapped inside component-1-wrapper, therefore it will apply only to component-1-wrapperclass
.component-1-wrapper{
// all the styles for component-1 here
.class-hello{
// styles
}
}
You can compile your css with sass and put all the css(seperated by modules) in seperate folder.Start the filenames by _, sass can import them:
You can refer your styles-main.scss in app.ts file
#component({
styleUrls:['styles/styles-main.scss']})
The style-sheets will be structured this way and individual component's class styles will be applied to particular component since there is a wrapper class in html
Hope it helps!!!!!!

Resources