How to share LESS or CSS files in Angular 7 application? - css

On the src root of an Angular 7 application I have 3 less files:
styles.less (global styles)
constants.less (less constants like colors, fonts, ...)
reset.less (css reset)
And I have the following on angular.json under build:
"styles": [
"src/resets.less",
"src/constants.less",
"src/styles.less"
]
In styles.less, to use constants, I needed to add the following:
#import (reference) 'constants.less';
The problem is how to use the constants inside a component's less files?
As an example let me show a HomeComponent (home.component.ts):
import { Component } from '#angular/core';
#Component({
selector: 'home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.less']
})
export class HomeComponent {
}
To use the constants.less I need to add to home.component.less the following:
#import (reference) './../../constants.less';
This makes it work but I have a few questions:
Can I reference constants.less somehow without './../..'?
Should I load constants.less in HomeComponent styleUrls?
Should I move constants.less to a shared folder instead of having in src root?
I placed it there because styles.less is in src root and is using it.
So I though I needed to load it using the angular.json definition file.

Related

import additional scss as theme on demand in angular

I am implementing admin panel for my application and the same has been lazy loaded, but I would like to speparate scss for admin panel. Say:
Public Portal
ecom-blue.scss
Admin Panel:
ecom-blue.scss
ecom-admin.scss
As of now I am importing both the CSSs in theme.scss like this way:
#import '~#angular/material/theming';
#include mat-core();
#import "themes/ecom-blue";
#import 'themes/ecom-admin';
$background: map-get($ecom-theme, background);
$foreground: map-get($ecom-theme, foreground);
which is further imported in app.scss this way:
#import "scss/variables";
#import "scss/themes";
#import "scss/views";
In angular.json
"styles": ["src/assets/styles/app.scss",
"node_modules/font-awesome/css/font-awesome.css"]
The problem with this approach is that the style.css (compiled file) will be having both the themes whereas I just want rent of the css to be included where my admin router layout is activated as per lazy loading.
may I know the best approach for this so that style.css file should be divided as per module and also to be loaded when required.
Edit:
This is how my router component look like:
#Component({
selector: 'app-auth-layout',
templateUrl: './auth-layout.component.html',
styleUrls: ['./../admin-layout.scss'],
// encapsulation: ViewEncapsulation.None
})
and this is how it is lazy loaded:
{
path: '',
component: AuthLayoutComponent,
children: [
{
path: 'admin4556',
loadChildren: () => import('./views/admin/admin.module').then(m => m.AdminModule),
data: { title: 'Admin', breadcrumb: 'Admin'}
}
]
},
UPDATE: If you will use ViewEncapsulation.None, yes, this allows you to apply base styles for children components, for example, if you style tag <p> in the parent component, the same style for <p> will be applied in the children component. BUT this is not the best practice. So if you sometimes will want to change your style in the child you need to add !important or add more points to your element to make it more specific. Will be better if you move out all common styles to BaseTheme or even styles.scss, and leave some specific styles inside lazy-loaded components. '' helps if you want to split your routes by different style areas if you have only one area base style you can go with styles.css only.
ORIGINAL:
If you want to apply some common style, for example, to user and admin components, and at the same time have some styles lazy-loaded specifically to each of them, you can do it with '' route. This is not some specific route, it's just skipped and goes further to children, but this allows us to add additional styles before it. It looks like this:
{
path: '',
component: BaseTheme, //base style
children: [
{ path: 'adminpanel', loadChildren: () => import('./adminpanel/adminpanel.module').then(m => m.AdminPanelModule) } //inside we add specific style
{ path: 'userpanel', loadChildren: () => import('./userpanel/userpanel.module').then(m => m.UserPanelModule) } //inside we add specific style
]
}

Angular 4 - Not use styles from angular-cli.json

I have an angular 4 application where I have the global styles and scripts in angular-cli.json. Then I worked separately on the Landing page. After I turn the landing page into an angular component, I add all its styles in angular-cli.json as well. And now my landing page's bootstrap conflicts with global bootstrap in node_modules and my application breaks.
Currently angular-cli.json looks like this:
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
"./dist/css/landing/bootstrap.min.css",
"./dist/css/landing/font-awesome.min.css",
"styles.css",
"./dist/css/AdminLTE.min.css",
"./dist/css/skins/_all-skins.min.css",
"../node_modules/froala-editor/css/froala_editor.pkgd.min.css",
"../node_modules/froala-editor/css/froala_style.min.css"
],
This is in landing.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-landing',
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.css']
})
export class LandingComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
I am almost missing my deadline, I can not resolve the conflicts between two huge css files. I was wondering if I could keep my Landing Page styles separated from application styles. Any help will be largely appreciated. Thank you.
You could try encapsulate your landing page as follows.
ViewEncapsulation.Native will wrap your component and its styles within a shadow root. Change your component style file to scss and import those styles in component style file and delete them from .angular-cli.json.
#Component({
selector: 'app-landing',
templateUrl: './landing.component.html',
styleUrls: ['./landing.component.scss'],
encapsulation: ViewEncapsulation.Native
})
export class LandingComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
landing.component.scss
#import '<path-to-dist>/dist/css/landing/bootstrap.min.css';
#import '<path-to-dist>/dist/css/landing/font-awesome.min.css';
When you inspect DOM, you'll see app-landing as encapsulated.
Edit
Alternatively, you can use ViewEncapsulation.Emulated which is default (you do not have to set it within metadata). What this will do is to create custom attributes with all the styles and add those attributes to your markup as well. Shadow DOM may not be supported in some browsers. Try both and if Emulated works for you, use that.

Angular2: How to import a stylesheet from node_modules?

Question: In my Angular2 (4.0) app, how can I import stylesheets (css) from a module in node_modules?
I have a module located here:
node_modules/#swimlane/ngx-datatable
I want to import this stylesheet:
node_modules/#swimlane/ngx-datatable/release/index.css
I've tried the following approaches, with no luck:
In my components own scss file:
#import '~#swimlane/ngx-datatable/release/index.css';
In my component:
#Component({
encapsulation: ViewEncapsulation.None,
selector: 'site_table',
template: require('./site_table.html'),
styleUrls: ['./site_table.scss', '#swimlane/ngx-datatable/release/index.css']
})
Because you're already using SCSS, in your ./site_table.scss import it like so
#import "~swimlane/ngx-datatable/release/index";
Note: do not add the extension.
It will import stylesheet from node package. That served my well, hope it will do for you too. That way you just have to use single stylesheet in your component and it will look cleaner.
If you are using new the angular-cli with the angular.json file and not webpack, the tilde (~) in #sickelap's answer probably doesn't work for you.
Instead what you can do is add this in your angular.json file:-
...
"styles": [
...
],
"stylePreprocessorOptions": {
"includePaths": [
"node_modules/#swimlane"
]
},
...
Then, in your component's .scss file, insert this:
#import "ngx-datatable/release/index";
Note that the .css extension is not required.
Try it with a complete relative url:
#Component({
encapsulation: ViewEncapsulation.None,
selector: 'site_table',
template: require('./site_table.html'),
styleUrls: [
'./site_table.scss',
'../../node_modules/#swimlane/ngx-datatable/release/index.css'
]
})
Didn't tried your notation but node package resolution might not work without webpack. I may be wrong though.

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";`
}
}
}
};

How to use SASS for components style in Angular 2?

In Angular 2 when we define a component we can specify a styleUrls property to the decorator which points to a set of stylesheets to be applied to the component:
#Component({
selector: 'the-app'
templateUrl: 'templateFile.html',
styleUrls: ['componentStyles.css', 'moreComponentStyles.css']
})
export class TheAppComponent {}
Now, what if I want to write these styles with SASS?
I know I would need to use Gulp or Grunt to transpile the SCSS stylesheets to plain CSS. But this makes me confused on how we would correctly point Angular to the correct stylesheets.
How could I organize this workflow of using SASS with Gulp/Grunt together with Angular 2? How to use SASS to write the Angular 2 components styles?
After following this wiki, I got some Error: Uncaught (in promise): Expected 'styles' to be an array of strings which I resolved using this answer.
Final solution is here:
home.component.ts:
import { Component } from '#angular/core';
#Component({
selector: 'home',
template: require('./home.component.html'),
styles: [ String(require('./home.component.scss')) ]
})
export class HomeComponent { }
webpack.conf.js: (part of it)
{
test: /\.(css|scss)$/,
loaders: [
'style',
'css',
'sass',
'postcss'
]
},
You can use .scss in Component like this-
styles: [require('normalize.css'), require('./app.scss')],
See if this helps.
I'm using it this way:
import {Component} from "#angular/core";
// for webpack
require('./footer.scss');
#Component({
selector: 'footer',
templateUrl: 'app/footer/footer.html',
styleUrls: ['app/footer/footer.scss'],
})
export class FooterComponent {}
Command line inside project folder where your existing package.json is: npm install node-sass sass-loader raw-loader --save-dev
In webpack.common.js, search for "rules:" and add this object to the end of the rules array (don't forget to add a comma to the end of the previous object):
{
test: /\.scss$/,
exclude: /node_modules/,
loaders: ['raw-loader', 'sass-loader'] // sass-loader not scss-loader
}
Then in your component:
#Component({
styleUrls: ['./filename.scss'],
})

Resources