Carbon design system global scss takes forever to build - css

I'm trying to apply g10 theme from Carbon Design System(Vue). But it takes about 12-15 mins to compile every time I save a file.
Is there a way to add styles for only the components I use?
If not, how do I reduce the build time?
Is there a way to remove watch on scss files so I can save compile time when working in Vue files?
#import "#carbon/themes/scss/themes";
$carbon--theme: $carbon--theme--g10;
// Use the gray 10 theme
#include carbon--theme();
#import "carbon-components/scss/globals/scss/styles";
#import "#carbon/grid/scss/grid";

We workaround this by having all the Carbon related styling in the App.vue file, which imports another component (e.g. AppContent.vue) which contains the content for the entire app.
This means that the Carbon styling is only compiled when you make changes to the App.vue, and as everything is in AppContent.vue, you'll only need to make changes to this file rather than App.vue.
App.vue:
<template>
<app-content></app-content>
</template>
<script>
import AppContent from "./AppContent.vue";
export default {
components: { AppContent }
};
</script>
<style lang="scss">
#import "./styles/carbon";
#import "./styles/_carbon.scss";
</style>
AppContent.vue:
<template>
<!-- the rest of your app -->
</template>
<script>
// the rest of your app
</script>
<style>
/* the rest of your app */
</style>

Related

CSS splitting per page in Next.js

I need my css stylesheet split into many files, one per each Next.js page. How to implement this?
I tried to use next-css and just import a css-file into each page. It almost works. However the css-file is not loaded on Link navigation. Authors of Next say it's not implemented:
https://github.com/zeit/next-plugins/issues/282#issuecomment-523128645
I also tried using styled-jsx. It has several problems for me. It has many bugs on its Issues page. I also failed to make styles visible throughout child components with this approach.
You can import a module.css (import style from 'root/styles/MyStyle.module.css) and use as follows.
This is your component:
import style from '../../styles/components/Header.module.css'
export default function Header() {
return (
<h1 className={style.header}>
Hello World
</h1>
);
}
This is your CSS:
.header{
color: #fff;
width: 100%;
height: 80px;
}
Note that the CSS class is used as the components className;
Or, inside the react component, you can try adding the tag <style jsx>{ your_CSS_here }</style>.
According to Next documentation each page uses the styled-jsx library. But you can still use other CSS-in-JS libraries such as Styled Components and Emotion.
Next apps has also support for using sass that allow you to import .css and .scss files.
For more information you can check the Vercel Docs. I also recommend you to check the Learning area.
You can create your seperate css files and on each component that you need specific styling you import the css file that is unique to that component. so for example say you have a Component in file file1.js then you can import styles specific to this component in the file file1.css same happens for another file file2 with css file2.css
import './file1.css'; //importing the style specific only for this component
function File1(){
const [processing, setProcessing] = useState(false)
return (
<> </>
)
}
export default File1
Similarly for the second file
import './file2.css'; //css file specific to this component
function File2(){
const [processing, setProcessing] = useState(false)
return (
<> </>
)
}
export default File2

webpack: scoping all SCSS under vue app selector

I am writing a vue app that renders inside a page on a "traditional" server-rendered site, in this container:
<div id="account-summary-container"></div>
Things work great when developing locally. But when run within the context of the website there is alot of style collision, because both my app and the website's styles are global. My app screws up styles on the entire site.
How can I scope all styles in my app to be local to the selector my app is rendered within?
My app uses bootstrap 4 styles which I am loading with css-loader.
I have webpack.config.js entrypoints like this:
entry: {
app: ["./src/scss/styles.scss", "./src/app.js"]
},
and styles.scss looks like:
#import '~bootstrap/scss/bootstrap';
#import '../css/feather.min.css';
#import '../css/icomoon-spinners.css';
#import url('https://fonts.googleapis.com/css?family=Maven+Pro:400,500,700,900');
#import 'helpers/variables';
#import 'helpers/mixins';
#import 'helpers/placeholders';
...
I am thinking css-modules might be the answer, but I can't figure out how to tell css-loader to make ALL styles local to #account-summary-container. I tried this in styles.scss:
:local(#account-summary-container) {
composes: "~bootstrap/scss/bootstrap";
composes: "../css/feather.min.css";
...
}
And it scoffed at my lame attempt with:
Error: composition is only allowed when selector is single :local class name not in ":local(#account-summary-container)", "#account-summary-container" is weird
I'm wondering if I am approaching it totally wrong. I'm hoping to not have to do alot of rewriting of styles.
In order to target only components inside of your Vue instance you have to use scoped styles. It is kind of a pain because you can't scope the css on the "main" App.vue file and let all children inherit it - you have to use scoped styles on each component that need it, which may result in more requests than you'd like..
As an example (I tested this and it should work)..
<template>
<!--
VUE/COMPONENT TEMPLATE
-->
</template>
<script>
export default {
/* ***********************
VUE/COMPONENT CODE
*********************** */
};
</script>
<!--
*********************************************************
***** SCOPE CSS PER COMPONENT ****************************
***** IMPORT VIA 'src="./path/to/cssfile.css"' ***********
**********************************************************
-->
<style scoped src="../css/style.css">
</style>
Found the answer. Pretty simple. Should had a V8 (conk).
.pony {
#import 'sub';
font-size: 100px;
}

How to generate multiple css files from separate scss source files arranged per component?

I have the following vue component Test.vue an would like to split up this css into test.css along with my other component Home.vue's css to be home.css. However everything compiles into app.css and merges everything.
<style lang='scss'>
h2 {
color: 1px solid red;
}
</style>
<script>
export default {
name: 'test',
}
</script>
<template>
<div class='Test'>
<h2>test</h2>
</div>
</template>
I am using this to build an html and css compiler for another project so I don't have to code in it, but rather just copy the structure from the prod html+css from this vue build. This way I can just copy over these separate test.css and home.css files to my other system. Right now though, it combined styles and there's no per component decoupling of styles.
I don't really know where to start in splitting up the css, I've been googling for hours.
current:
dist
--/css
----app.css
desired:
dist
--/css
----app.css
----test.css
The Vue Webpack loader's documentation suggests using mini-css-extract-plugin for Webpack 4 or extract-text-webpack-plugin for Webpack 3. Have you tried using that?

Not entirely sure where am I supposed to write my CSS in a Vue SPA

Up until now, I've always used a single CSS file when creating multiple page applications which would store all my CSS rules.
Now that I'm using Vue.js and components, I am not sure where to write my CSS.
I could write the CSS in the <style></style> tags of a component but to me this only makes sense if the CSS is only used for this specific component. This leaves me wondering where should I write CSS which I would like to be applied globally to everything.
Imagine I have some CSS which I want to be applied to everything like this snippet:
*, *:after, *:before {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-decoration: none;
}
Where would I write it?
Until a better solution I can offer two suggestions:
1. In App.vue file
If it's just a small amount of code, put it in your App.vue file
As you said:
"I could write the CSS in the tags of a component but to me this only makes sense if the CSS is only used for this specific component."
If you put CSS in the in the <style></style>in any .vue files that's part of your project it's going to be global.
<style></style> get's applied to the whole project unless you add scoped to the tag.
<style scoped>
body {
background: green; /* This won't effected your main <body> tag unless you actually have a `<body>` inside the `<template>` of that file */
}
</style>
2. Import a separate file containing only CSS (updated and easier)
From #Fabjan in the comments.
Just import the .css file in your main.js file:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './assets/lib/css/reset.css' // my own reset file
import './assets/lib/css/myMain.css' // global stylesheet
Make sure to put it before your run your app. new Vue({})
(3. My previous answer:)
You can create a styles.vue and add all your global styles there inside <styles></styles> without scoped. (this worked for me)
Then inside your main.js file you write:
import GlobalStyles from "./assets/lib/css/styles.vue"
Vue.use(GlobalStyles)
Make sure your styles.vue contains at least on tag inside for it to import properly.
<template>
<div class="empty">
</div>
</template>
<style>
body {
background: red;
/* The rest of your Global CSS code */
}
</style>
This feels really tacky but it worked for me now.
Hope it helps and I'd love some feedback or comments if people have better solutions.
Here is my solution to configure global scss with my project that using Nuxt.
Assume that you already have node sass and sass-loader installed.
In nuxt.config.js file add your SCSS path from static or assets folder
css: [
'#/assets/scss/main.scss'
]
Bonus: if you don't like this way maybe you can get a try nuxt-sass-resources-loader

Sharing common CSS across VueJS components

I'm working on the VueJS 2 project and I'm trying to clean the code but struggle with scoped styling.
Here is my requirements. :)
I have 3 components those are very similar to each others, so I decide to use mixins to merge the code into one file. Each component will use that mixins of both template and vuejs. When I want to customize the conditions of a particular component, I can simply override the code in it and it is working fine in this part.
However, one thing that I want to do more is to move the scoped style to the mixins as well. At the moment, the style is wrapped in <style lang="scss" scoped></style> tag and this style works very well on its component but I have to duplicate the styling codes into all 3 components.
I know I can add these styles to the global css file but I don't want some styles to the global scope, only one these 3 components will apply for these.
Is it any way to add these styles and apply to mixins?
What is the best practice to code this particular case?
Vue makes this easy.
Solution
To use shared styles in a component you can do this.
MyComponent.js
<template>
</template>
<script>
</script>
<style lang="scss" scoped>
#import '#/scss/shared-styles.scss';
#import 'styles.scss'; // this is the regular CSS used just by the component
</style>
Alternative
You can also import the shared CSS files in the component CSS file instead like below.
MyComponent.js
<template>
</template>
<script>
</script>
<style lang="scss" scoped>
#import 'styles.scss';
</style>
styles.scss
#import '#/scss/shared-styles.scss'
// rest of your component CSS
Automatically import global styles
If you want certain styles to be available in ALL your components you can do this.
vue.config.js
module.exports = {
...
css: {
loaderOptions: {
sass: {
prependData: `
#import "#/scss/global.scss";
`
},
},
},
}
I just found out the scoped style also affect on the child components as well.
Therefore, I found the solution, not sure is it the best practice but I feel very nice for it.
Create a WrapperComponent and I put the scoped style here and a small template.
<template>
<div>
<slot></slot>
</div>
</template>
<style lang="scss" scoped>
/* css style that will apply to all children */
</style>
What happen here is that, when we wrap whatever components with this WrapperComponent, the template will pass on the HTML via slot without any modification and style will be able to apply from now on.
In mixins, I import this wrapper and wrap the component template with the WrapperComponent. Here is the example.
import WrapperComponent from './WrapperComponent'
let MyMixins = {
template: `<wrapper-component>
<div>
Whatever HTML code here
</div>
</wrapper-component>`,
components: {
WrapperComponent,
},
};
When we use this mixins or a child component, the style from WrapperComponent will be automatically applied and also can be used with other groups of components those want to use the same parent style.
Perhaps use modules instead of setting up a style section with a scoped attribute.
https://vue-loader.vuejs.org/en/features/css-modules.html
This way your CSS will still be scoped and not part of your global styling.
I just dropped my fadeTransition.css file into my vue app /assets folder, and import like this:
<template>
<transition name="fade">
<div v-if="showContent">test</div>
</transition>
</template>
<script>
import '#/assets/fadeTransition.css';
// component definition
</script>
fadeTransition.css
/* fade menus in, not out */
.fade-enter-active {
transition: opacity .5s;
}
.fade-enter {
opacity: 0;
}
Clean and simple. Should work for scss, too.
Cheers!

Resources