Angular Material 15: How to customize the styling of buttons and input fields?
Asked Answered
H

3

6

I would like to override the font width in Angular Material 15 buttons and input fields.

Material docs say here that I should do this in my stylesheet:

@use '@angular/material' as mat;

$my-custom-level: mat.define-typography-level(
  $font-family: Roboto,
  $font-weight: 400,
  $font-size: 1rem,
  $line-height: 1,
  $letter-spacing: normal,
);

I don't think this code actually "applies" my font changes, I guess it needs to be applied to the current theme or something, I tried various things but couldn't figure out how to apply this. Any hints would be appreciated.

I tried to create my custom theme but couldn't figure out where to apply $my-custom-level:

$config: mat.define-typography-config();

$theme: mat.define-light-theme((                                                    
    typography: $config,
));

@include mat.input-typography($theme);
Higley answered 26/12, 2022 at 20:55 Comment(0)
S
16

It took me quite some time to get to a solution of your problem: Styling the buttons less complicated since $button is a default property in typography-config. Yet for the input-fields I needed to create a custom-property in typography-config and then manually assign it via @mixin to the class-selector of the material-input-fields (.mat-mdc-form-field).

@use '@angular/material' as mat;
@use "sass:map";

/* Styles to be applied to buttons */
$my-custom-button: mat.define-typography-level(
  $font-family: 'Roboto',
  $font-weight: 500,
  $font-size: 2rem,
  $line-height: 1,
  $letter-spacing: 'normal'
);

/* Styles to be applied to input-fields */
$my-custom-input: mat.define-typography-level(
  $font-family: 'Roboto',
  $font-weight: 400,
  $font-size: 1rem,
  $line-height: 1,
  $letter-spacing: 'normal'
);

/* Merge custom configs into existing config */
$my-typography-config: map.merge(
    mat.define-typography-config(
        /* 'button'-property will work out of the box */
        $button: $my-custom-button
    ),
    (
        /* 'input'-property will have to be assigned under '@mixin typography' further below */
        'input': $my-custom-input
    )
);

/* Apply custom config */
@include mat.all-component-typographies($my-typography-config);

/* Let's assign the custom property 'input' that we defined above */
@mixin typography($theme) {
    $custom-typography-config: mat.get-typography-config($theme);
    
    .mat-mdc-form-field {
        @include mat.typography-level($custom-typography-config, 'input')
    }
}

/* Define custom app-theme based on custom-configs */
$app-theme: mat.define-light-theme(
    (
        typography: $my-typography-config,
    )
);

/* Apply custom app-theme */
@include typography($app-theme);
Spherical answered 26/12, 2022 at 23:32 Comment(3)
thanks so much, this indeed worked! It's a bummer this is so complicated to achieve.Higley
Can you please mark it as the accepted answer then. I took me more than 2 hours to find it out...Spherical
done, long time user, first time I asked a question, I couldn't find the button :) thanks again for your help!Higley
B
1

Coming from Angular 14 to 17 - buttons still work, but I guess the input were either deprecated, no longer persist in the official typography documentation or just bugged.

This is why I just overrode them in my _mat_overrides.scss file:

// input: mat.define-typography-level(1rem, 1.125, 400, $base-font, 1.5px),
.mat-mdc-input-element {
  font-size: 1rem !important;
  line-height: 1.125 !important;
  font-weight: 400 !important;
  letter-spacing: 1.2px !important;
}

// Floating placeholder, select - selected option & all options
.mdc-floating-label,
.mat-mdc-select,
.mat-mdc-option {
  font-weight: 400 !important;
}
Burgage answered 18/1 at 12:55 Comment(0)
P
1

As the listed solutions were either not restrictive enough (.mat-mdc-form-field) or too restrictive for my use case (due to !important), I came up with two possible alternatives.

  1. Motivated by this answer, you might use double class names for your selectors to trump single class names, which are used by Material itself:
@mixin typography($theme) {
    $custom-typography-config: mat.get-typography-config($theme);
    
    .mat-mdc-form-field.mat-mdc-form-field {
        @include mat.typography-level($custom-typography-config, 'input')
    }
}

... while this works for some use cases, it is necessary to extend the list of selectors:

@mixin typography($theme) {
    $custom-typography-config: mat.get-typography-config($theme);
    
    .mat-mdc-form-field.mat-mdc-form-field,
    .mat-mdc-select.mat-mdc-select, 
    .mat-mdc-menu-item.mat-mdc-menu-item 
    // further selectors are necessary
    {
        @include mat.typography-level($custom-typography-config, 'input')
    }
}

... which can be problematic when adjustments are made.

  1. A more generic solution is motivated by this answer and allows to overwrite the typography of the component types itself:
/* Apply custom config */
@include mat.all-component-typographies($my-typography-config);

/* Apply further overwrites */
$form-typography: mat.m2-define-typography-config(
    $body-1: mat.m2-define-typography-level(1rem, 1, 400, 'Roboto'),
);
@include mat.checkbox-typography($form-typography);
@include mat.form-field-typography($form-typography);
@include mat.input-typography($form-typography);
@include mat.menu-typography($form-typography);
@include mat.option-typography($form-typography);
@include mat.radio-typography($form-typography);
@include mat.select-typography($form-typography);

You might also exclude several component types or include further ones.

Pyrone answered 2/7 at 10:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.