Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change styles.scss dynamically in Angular

Tags:

angular

I want to apply dynamically SCSS styling according to a variable, known prior to Angular bootstrapping. Is it possible to change styles.scss programmatically? In main.ts before bootstrapping, I want to add dynamically a line like:

@import 'assets/styles/customerA/_themes.scss';                        or  @import 'assets/styles/customerB/_themes.scss'; 

depending on a variable's value coming from the server.

If the above is not feasible, is there any way to populate styles.scss with the content of another file which will be defined on the server? I want to change styles.scss and not any other "local" scss file.

like image 787
Unknown developer Avatar asked Oct 23 '18 15:10

Unknown developer


People also ask

Can SCSS variable change dynamically?

SCSS is compiled to CSS during compile time, and SCSS variables are replaced with resolved value during compile time, which means there is no way to change the variable during run time. However, CSS variables just sits there during run time, and you can dynamically CRUD them during run time with JavaScript (Web API).

How do I change variables in SCSS?

A Sass variable must be initialized with a value. To change the value, we simply replace the old value with a new one. A variable that's initialized inside a selector can only be used within that selector's scope. A variable that's initialized outside a selector can be used anywhere in the document.

How do I change the style file in angular?

It is supposed to be for changing the environment file, but I am guessing it should work also for styles. You can change the styles file using fileReplacements in angular.json, but this would require you to rebuild the app each time. Now you can run ng serve -c customerA or ng serve -c customerB to get the relevant stylesheet.

How to migrate from CSS to SCSS stylesheet format in angular?

A quick and easy way to perform the migration is to use the schematic NPM package schematics-scss-migrate. Read more on what this schematic package does on NPM. A schematic to migrate from CSS to SCSS stylesheet format for an Angular CLI project npm i --save-dev…

How do I set global styles for a theme in angular?

You'll notice in their angular.json file that they have a main.scss which is used regardless of which secondary style is chosen. This file will handle any global themes you need. Notice in their main.scss they import several Sass partials. These allow them to set global styles for any theme.

How to name the stylesheets of Our components in angular?

Now that we have achieved that, we have to change the source to use the new files extension, as a good Angular convention suggests that we name the stylesheets of our components by suffixing them with. component.


Video Answer


1 Answers

I would recommend following the general form of the Angular Material Website: https://github.com/angular/material.angular.io/blob/master/angular.json. It's worth cloning this repo and playing around with it locally. There are several moving parts.

In your angular.json file you'll add the css as follows. Notice that you'll need to compile your scss to css separately for this to work. They do this in the tools/build-theme.sh script. :

{   "input": "src/assets/customer-1-theme.css",   "lazy": true,   "bundleName": "customer-1-theme" }, {   "input": "src/assets/customer-2-theme.css",   "lazy": true,   "bundleName": "customer-2-theme" }, 

Then, look at their style manager: https://github.com/angular/material.angular.io/blob/master/src/app/shared/style-manager/style-manager.ts

You'll create a function to dynamically add and remove this style sheet as needed:

function createLinkElementWithKey(key: string) {   const linkEl = document.createElement('link');   linkEl.setAttribute('rel', 'stylesheet');   linkEl.classList.add(getClassNameForKey(key));   document.head.appendChild(linkEl);   return linkEl; } 

Then in the ThemePicker you'll set up an observable to manage the theme setup and removal. See (https://github.com/angular/material.angular.io/blob/master/src/app/shared/theme-picker/theme-picker.ts):

installTheme(themeName: string) {   const theme = this.themes.find(currentTheme => currentTheme.name === themeName);   if (!theme) {     return;   }   this.currentTheme = theme;   if (theme.isDefault) {     this.styleManager.removeStyle('theme');   } else {     this.styleManager.setStyle('theme', `assets/${theme.name}.css`);   }    if (this.currentTheme) {     this._themeStorage.storeTheme(this.currentTheme);   } } 

Personally, I went about it a slightly different way, but that meant that the scss compiles into one css file, and the class is selected dynamically. Their way adds an extra build step, but allows the compiled scss to be lazy loaded.

Managing Global Styles

You'll notice in their angular.json file that they have a main.scss which is used regardless of which secondary style is chosen. This file will handle any global themes you need. Notice in their main.scss they import several Sass partials. These allow them to set global styles for any theme. You can investigate how these are used, the main reason they are using partials here is that they can pass variables from the secondary sass files up to these partials through the use of mixins.

@mixin material-docs-app-theme($theme) {   $primary: map-get($theme, primary);   .docs-primary-header {     background: mat-color($primary); 

map-get is a Sass function, which allows you the ability to define an object and use its values in Mixins. Material design has a sass-function they are using here, but you could use an easier method grab a custom color in your main.scss. In your style-a / style-b scss create a custom theme.

$my-custom-theme: (   background-color: #ffff,   button-background: rgba(200, 200, 200, 0.6),   foreground: #34383c ); 

Then, you would change their @include to:

@include material-docs-app-theme($theme, $my-custom-theme); 

The material-docs-app-theme mixin would change to:

@mixin material-docs-app-theme($theme, $my-custom-theme) {   $background-color: map-get($my-custom-theme, background-color);   .our-background {     background-color: $background-color;   } 

This allows you the opportunity to define custom colors in the individual lazy-loaded style sheets and have them available in a global main.scss. Mixins and Partials from Sass make this possible.

like image 161
David Rinck Avatar answered Sep 30 '22 14:09

David Rinck