Can't override the angular material theme with my css properties

10,433

Solution 1

Please check out this minimal example (I've had to adjust the font-family to make this example work).

You're overwriting some of your font style definitions. Either define your font-family, -size and -weight all separately like in the following adjusted .Arabic definition:

.Arabic {
  font-family: 'Shadows Into Light', cursive;
  margin: 0;
  /* background: #fff; */
  font-size: 16px/20px;
  font-weight: normal;
  color: red;
  text-shadow: 0 0 0 #1072BA;
}

Or set the font properties with the shorthand declaration like in this modified example:

.English{
  margin: 0;
  /* background: #fff; */
  font: normal 16px/20px 'Pacifico', cursive;
  color: green;
  text-shadow: 0 0 0 #0078be;
}

Edit

To answer to your comment / edited question:

I find the font in the computed values but it is striked through and not applied, it is only applied if I apply the class specifically on the mat-form field

You have to apply the class explicitly on .mat-form-field if you want to change it because within the prebuilt-themes/indigo-pink.css it's defined explicitly as

.mat-form-field{
    font-size:inherit;
    font-weight:400;
    line-height:1.125;
    font-family:Roboto, "Helvetica Neue",sans-serif
}

same for the label color.

With CSS you always have to be at least as specific as the already existing style definition.

You could do this:

.Arabic .mat-form-field,.mat-form-field-appearance-legacy .mat-form-field-label,
.mat-input-element,.mat-form-field.mat-focused .mat-form-field-label{
  font-family: 'Shadows Into Light', cursive;
  margin: 0;
  /* background: #fff; */
  font-size: 16px/20px;
  font-weight: normal;
  color: red;
  text-shadow: 0 0 0 #1072BA;
}
.Arabic .mat-form-field.mat-focused .mat-form-field-ripple{
  background-color: red
}

But that's not very nice I think. Better solution would be to create two custom themes, one for each language and set the colors and fonts there. This way your color and font definitions will apply to the nested elements automatically. This guide is a good read regarding custom themes.

EDIT 2: angular material theming

As mentioned in my previous edit, creating custom themes might be the better solution for your problem. Custom themes in angular material are quite powerful, however you need to set up quite a bit first. After that it's just a matter of a few lines to adjust the color, fonts etc.

I've created a new stackblitz where you can see the set up of a default and two custom themes and the adjustment of color and fonts of the material-form-field. I've commented every section but I'll briefly explain here as well:

The general structure of your styles.scss should be:

  • importing the required angular material mixins
  • defining the fonts
  • defining/importing custom component themes
  • defining a default theme
  • defining all other custom themes

After you've imported @import '~@angular/material/theming'; you can start adjusting the fonts (if you wish). To do so, you just need to define a new mat-typography-config e.g.:

$arabic-typography: mat-typography-config(
  $font-family: '"Shadows Into Light", cursive'
);

$english-typography: mat-typography-config(
  $font-family: '"Pacifico", cursive'
);

To apply those font-configs you need to and them over to the mat-core-mixin which takes care of the rest: @include mat-core($english-typography);. Now, if you only want to apply your font-config to a specific custom theme, you have to add your font-config within the theme definition.

A theme is defined by the following structure: define your desired main colors an the theme by using the mat-light-theme-mixin. To apply the theme, use @include angular-material-theme(<theme name>);

$app-primary: mat-palette($mat-indigo);
$app-accent:  mat-palette($mat-amber, A200, A100, A400);
$app-warn:    mat-palette($mat-red);
$app-theme:   mat-light-theme($app-primary, $app-accent, $app-warn);
@include angular-material-theme($app-theme); 

To achieve your multiple theme setup, you can wrap a theme definition within a CSS-class name like so:

.Arabic {
    $arabic-primary: mat-palette($mat-orange);
    $arabic-accent:  mat-palette($mat-blue, A200, A100, A400);
    $arabic-warn:    mat-palette($mat-red);
    $arabic-theme:   mat-light-theme($arabic-primary, $arabic-accent, $arabic-warn);
    @include mat-core($arabic-typography);
    @include angular-material-theme($arabic-theme);
}

Now, the .Arabic theme is only applied if your html elements is a descendant of an element with the .Arabic class. Additionally I've added @include mat-core($arabic-typography); which tells the theme engine to just apply the $arabic-typography to the $arabic-theme.

Final step to accomplish your styling is to define a custom component theme which styles the mat-form-fields as desired. This is now a matter of a few lines:

@mixin my-custom-component($theme) {
  // retrieve variables from current theme 
  $primary: map-get($theme, primary);

  // style element
  mat-form-field, .mat-form-field-appearance-legacy .mat-form-field-label {
    color: mat-color($primary);
  }
}

This custom component theme is then added to your custom themes by adding the line @include custom-components-theme(<theme name>); to each theme definition. (custom-components-theme is a little helper function. Read more about it in the stackblitz).

That's it. If you need to adjust more components, you just have to create a custom theme for that component and add it to the custom-components-theme mixin.

Solution 2

If you're trying to override an Angular Material style, you can do it with deep

parameter infront of it like so:

::ng-deep .mat-step-header .mat-step-icon {
  background-color: #f6871f;
}

Solution 3

Usually when I have worked with Material styling libraries they are styled with very high specificity. If you inspect the elements in your browser you will see the order of when the styles are applied. Like here, you will see that some properties are being overwritten because of the more specified properties above.

example

See if your styles are too far back in the priority queue. If they are not there at all, there is something wrong with the import.

Share:
10,433
Ahmed Elkoussy
Author by

Ahmed Elkoussy

I always understand the business &amp; the customer needs then deliver the simplest solution possible for the business needs, while still being capable of building complex solutions Ambitious, creative, self-motivated &amp; fast learner. Capable of solving complex challenges in an innovative &amp; effective manner. Passionate about web development &amp; crafting compelling UX in my apps. Solid experience in: NodeJS, ReactJS, Angular, Javascript, Ruby on Rails, python, Java Proud to be among the top 8% overall score in stackoverflow &amp; usually in the top 3% every quarter

Updated on June 11, 2022

Comments

  • Ahmed Elkoussy
    Ahmed Elkoussy about 2 years

    I am using Angular 6.0.8 with Angular Material theme version 6.4.0

    Whenever I try to slightly modify the material theme, it never works, as I always find the material theme properties to overwrite my CSS properties as follows:

    currentColor   .mat-input-element (material theme)
    initial        input, textarea, select, button (user agent stylesheet)
    #1072BA        .English
    #1072BA        .English
    #1072BA        body

    Only the first property is applied (the rest are striked through)

    I have tried multiple variations to solve this but none worked (like using important or changing the order of importing the themes)

    So what is the proper way to change small things in the material theme & the user stylesheet? (to make this English rule applied for example)

    My styles.scss is as follows, it works well only what overrides the Material theme like colors & fonts does not work:

    @import '~@angular/material/prebuilt-themes/indigo-pink.css';
    
    /* You can add global styles to this file, and also import other style files */
    
    /* prevent clicking in the wizard nav header */
    .mat-horizontal-stepper-header{
      pointer-events: none !important;
    }
    
    @font-face {
      font-family: 'Material Icons';
      font-style: normal;
      font-weight: 400;
      src: url(./assets/material_icons/material_icons.woff2) format('woff2');
    }
    
    .material-icons {
      font-family: 'Material Icons';
      font-weight: normal;
      font-style: normal;
      font-size: 24px;
      line-height: 1;
      letter-spacing: normal;
      text-transform: none;
      display: inline-block;
      white-space: nowrap;
      word-wrap: normal;
      direction: ltr;
      -webkit-font-feature-settings: 'liga';
      font-feature-settings: 'liga';
      -webkit-font-smoothing: antialiased;
    }
    
    .mat-radio-button{
      margin: 10px;
    }
    
    .mat-checkbox{
      margin-bottom: 10px;
    }
    
    .Done-numbers{
      color: red;
      font-weight: bold;
    }
    
    .finInfo-hint{
      color: gray;
    }
    
    .finInfo-success{
      color: green;
    }
    
    .Arabic {
      font-family: "AXtManal" !important;
      margin: 0;
      /* background: #fff; */
      font: normal 16px/20px Verdana;
      color: #1072BA;
      text-shadow: 0 0 0 #1072BA;
    }
    
    .English {
      font-family: "Rotis" !important;
      margin: 0;
      /* background: #fff; */
      font: normal 16px/20px Verdana;
      color: #1072BA;
      text-shadow: 0 0 0 #0078be;
    }
    

    Update 1:

    Please check out this stackblitz example , the problem is very clear in it

    1- I am expecting that the enclosing div with the Arabic class shall change the font & color of the contained material form fields but it doesn't (like the first field with Sushi, font is not changed)

    This is very important as all elements are enclosed in a div with ngClass that have either English or Arabic & I want to apply the class to all enclosed elements including the material form fields

    2- How to change the color of all the form labels from the blue to red or green ?

  • Ahmed Elkoussy
    Ahmed Elkoussy almost 6 years
    Thanks a lot for your explanation, I have used your stackblitz example to clarify my issue, also I have the font defined in another stylesheet that is applied successfully, I find the font in the computed values but it is striked through and not applied, it is only applied if I apply the class specifically on the mat-form field, please check my updated question for details
  • Ahmed Elkoussy
    Ahmed Elkoussy almost 6 years
    They are striked through in the computed values but I can't make them override the other properties, I have updated the question with more details & thanks for your help
  • Kristoffer Lund
    Kristoffer Lund almost 6 years
    Not sure totally get you end-goal here, but does this look like the solution you're looking for? Look at line 67-70 in the CSS: stackblitz.com/edit/angular-jwztdt?file=src/styles.css
  • coreuter
    coreuter almost 6 years
    @AhmedElkoussy I've adjusted my answer accordingly :)
  • Ahmed Elkoussy
    Ahmed Elkoussy almost 6 years
    thanks for your help, it actually works but it breaks the dropdowns badly, as the label is shown twice in them when using !important & without it no change happens
  • Ahmed Elkoussy
    Ahmed Elkoussy almost 6 years
    Thanks a lot for your help :) , but the code breaks if I use it for the 2 languages, I am sure there must be a way to overwrite the primary accent color & font that is easier than this
  • coreuter
    coreuter almost 6 years
    @AhmedElkoussy I've replied to your comment within my answer. Please try the new stackblitz and let me know if this solves your problem.
  • Ahmed Elkoussy
    Ahmed Elkoussy almost 6 years
    Thank you very much for the terrific answer! I had solved it but it was not fully compatible with Material theme & when I tried your answer it worked brilliantly (thought it is hard to understand to be honest as you said :) )
  • Magnus
    Magnus over 4 years
    I was wandering in the wilderness till I came across this sentence in your answer "you always have to be at least as specific as the already existing style definition"
  • Marijke
    Marijke over 2 years
    Just this one sentence of your answer helped me a lot "With CSS you always have to be at least as specific as the already existing style definition.". Fixed my problem!