Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicated styles on head and a lot of <style> elements

I'm quite happy with angular-material2 components but there are some weird behaviors that I don't understand and they don't have a proper documentation especially for teeming and customizing their components.

My project looks like:

.src
  --app
    --components
      --login-component
           login-component.html
           login-component.scss
           login-component.js
      --login-component
            home-component.html
            home-component.scss
            home-component.js
       --and so on ...
    app.component.html
    app.component.scss
    app.component.ts
    app.module.ts
    app.routing.ts
    --assets
    --environments
    --scss
      styles.scss
      _material2-theme.scss
      _variables-scss
      _utilities.scss
      _reset.scss
   favicon
   index.html
   and so on ....

In angular-cli.json I have modified the styles to look at scss/style.scss

...
"styles": [
        "scss/styles.scss"
      ]
...

the _material2-theme.scss looks like:

//////////////////////* THEMES */ Custom Blue Theme*/
@import '~@angular/material/theming';
@include mat-core();
$app-primary: mat-palette($mat-light-blue);
$app-accent:  mat-palette($mat-light-blue, A200, A100, A400);
$app-theme:   mat-light-theme($app-primary, $app-accent);
@include angular-material-theme($app-theme);

/*default palette forground/background*/
$light-foreground-palette: map-get($app-theme, foreground);
$light-background-palette: map-get($app-theme, background);

$primary: map-get($app-theme, primary);
$accent: map-get($app-theme, accent);

and inside of style.scss I am importing everything to be compiled with scss cli compiler

//////////////////////* CUSTOM */
@import "_material2-theme.scss";
@import "_reset.scss";
@import "_utilities.scss";
 //////////////////////* COMPONENTS */
 @import "~app/components/login/login.component.scss";

My question is after the scss is compiled we have in html head many style tags some of them duplicated and look like:

enter image description here

Everything seems to be compiled in one style that is added in head(tha one that has type attribute) and and after that each scss component splited in each css component with its separate style in head, and that is very weird. I am doing something wrong or is just tha way is working material2?

like image 941
mcmwhfy Avatar asked Jan 05 '18 13:01

mcmwhfy


3 Answers

The behavior you're seeing is caused by ViewEncapsulation.Emulated defined for material components.

First, you don't need to add styles for components to the global styles "scss/styles.scss":

//////////////////////* COMPONENTS */
@import "~app/components/login/login.component.scss";

If you do that, besides your styles getting duplicated you will lose style encapsulation because styles added for components/login/login.component.scss will become global.

Now, to the question why there are many style elements. When you use ViewEncapsulation.Emulated, and it's a default view encapsulation mode, Angular will put each component's style into its own style tag and add attribute to elements inside a component template. In material all components use emulated encapsulation mode so for each component the style tag is added.

If you add @Component({..., encapsulation: ViewEncapsulation.Native }) for your components, you will see the style for your components will be removed.

Here is the logic that adds the style tag:

export class DomSharedStylesHost extends SharedStylesHost implements OnDestroy {
  ...
  private _addStylesToHost(styles: Set<string>, host: Node): void {
    styles.forEach((style: string) => {
      const styleEl = this._doc.createElement('style');  <--- creates a style element
      styleEl.textContent = style;
      this._styleNodes.add(host.appendChild(styleEl));
    });
  }
like image 115
Max Koretskyi Avatar answered Oct 05 '22 18:10

Max Koretskyi


In Material design for Angular the stylesheet is split into:

  • style - margins, paddings etcetera that is linked from the component
  • theme - mostly colors that is build using the theme scss
  • typography - fonts & font properties that is built using the typography scss

This causes similar selectors, but with different properties inside.

I think it is the live development server that comes with angular cli or webpack that loads css dynamically which causes duplication of style tags. I believe this is not happening in a production build.

PS. Strange of you to add _reset.scss after anything else.

like image 20
jornare Avatar answered Oct 05 '22 19:10

jornare


I do not think it is due to having separate styles for each component. This issue is similar to what's there in a ngularjs-material as well.

Angular-material includes some default theme css as a const variable in JavaScript.

You can read a more on this issue , https://stackoverflow.com/questions/33466779/how-to-get-rid-off-angular-material-extra-styles-and-css-linked-by-it-forcefull

like image 30
Sajeetharan Avatar answered Oct 05 '22 19:10

Sajeetharan