How to place style.css behind style tags added by angular material

Viewed 640

I've added angular material to my project and after creating a custom theme I wanted to change the style of .mat-fab.

_theme.scss:

@use '~@angular/material' as mat;
@include mat.core();

$wb-nightblue: ( ... );
$wb-yellow: ( ... );

$wb-primary: mat.define-palette($wb-nightblue);
$wb-accent: mat.define-palette($wb-yellow, 500, 300, 800);
$wb-warn: mat.define-palette(mat.$red-palette);

$wb-theme: mat.define-dark-theme((color: (primary: $wb-primary, accent: $wb-accent, warn: $wb-warn)));

@include mat.all-component-themes($wb-theme);

.mat-fab {
   border-radius: 3px;
}

styles.scss:

/* You can add global styles to this file, and also import other style files */
@import '_theme';

The mat-fab button still doesn't show my custom border-radius, however. Taking a look at the page with the dev-tools I can see that my css-rule exists, but it is overwritten by the default material style. Apparently, angular material adds four <style>-tags to the end of the HTML header, just after my stylesheet gets added by angular, which then overwrite my added style.

  ...
  <link rel="stylesheet" href="styles.css">
  <style>/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJhcHAuY29tcG9uZW50LnNjc3MifQ== */</style>
  <style>.mat-button .mat-button-focu...</style> // contains a lot of angular material button related styles.
  <style>.mat-icon{background-repeat:...</style> // contains some angular material icon related styles.
  <style>/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJtYXAuY29tcG9uZW50LnNjc3MifQ== */</style>
</head>

Now this construct makes it of course pretty much impossible for me to overwrite default button styles without resorting to !important. I don't know what the sourceMappingURL styles are doing but I guessed they're responsible for the other two tags being added. I've tried to look for them in my project but couldn't find anything. Google wasn't any help either. If I just remove the styles in the html via developer tools, the buttons then lack the proper material style so they are required, but I'd like to have my styles.css placed at the end of the HTML head, so I can overwrite the parts I want.

I've also checked angular.json for any style entries but the only one is my styles.css, which isn't any surprise, since I'd have other stylesheet links in there instead of the direct <style>-tags.

Is there a way to get my stylesheet to the end of the head?

1 Answers

UPDATE

The reason the below does not work has nothing to do with Angular, but with CSS.

.mat-fab {
   border-radius: 3px;
}

Basically, CSS applies styles according to how specific they are. If you want a style to be applied over another one, you need to be more specific about it.

You can read more on this here.

Now onto possible solutions, which are three:

  1. The important!: A way to make your styles always apply over another is the use of the important! attribute. This means that your style will only be overwritten by another style with an important! that is more specific that yours.

Given that Angular Material avoids important! there is little change that this happens. The solution would then be:

.mat-fab {
   border-radius: 3px !important;
}
  1. Being more specific with material styles: Lots of people see the use of important! has an indicator that the CSS was poorly written. An alternative to this is simply being more specific with material on what styles we want to overwrite, like so:
.mat-button-base.mat-fab {
   border-radius: 3px;
}

In this case we are using Material's own class to specific that we want to apply our style not just to the mat-fab but to a html element that contains both mat-fab and mat-button-base. The mat-button-base class is a class that all buttons from Angular Material share.

  1. Define your own class and combine it: Similar to the previous sugestion, instead of using angular material, you can create your own class and combine it with the mat-fab like so:
.border-3.mat-fab {
   border-radius: 3px;
}

And in the html you would have:

<button mat-fab class="border-3">
  <mat-icon><!-- Icon here --></mat-icon>
</button>

This approach is clearer if somethings you will use the original material style and sometimes your own styling.

Keep in mind that in all cases, the styles need to be defined in a global style sheet.


According to the Official Documentation if you want to override the style of material component, you should create a file with all your custom styles, them pass it to the styles array of your angular.json.

The above describes how to find it:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "app-name": {
      ...
      "architect": {
        "build": {
          "options": {
            ...
            // Add the file here.
            "styles": [
              // By default, Angular adds the material theme you choose and the src/style.scss file, see below
              "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
              "src/styles.scss"
            ],
          }  
        }
      }
    }
  }
}

The file you are edditing is related to theming (color palettes and what not).

An example of this is the src/style.scss file. This file is created by default to allow you to create css that will be applied to all HTML Elements and components.

With the above in mind, I would advise that you add your code in the src/style.scss file like below:

/* You can add global styles to this file, and also import other style files */

.mat-fab {
   border-radius: 3px;
}
Related